X-Git-Url: http://git.megacz.com/?p=nestedvm.git;a=blobdiff_plain;f=src%2Forg%2Fibex%2Fnestedvm%2FRuntime.java;h=f28662078395080bbd32807501a4d52d2e0ee8de;hp=d6db76d7b4e39f73b70dffb3e9c58f3773019aa7;hb=6d6d9f59a2e6fe3b9e5b3563efcf0124bea4a672;hpb=56fb6d1d8da7faf3cc7e73130b11961af7529d13 diff --git a/src/org/ibex/nestedvm/Runtime.java b/src/org/ibex/nestedvm/Runtime.java index d6db76d..f286620 100644 --- a/src/org/ibex/nestedvm/Runtime.java +++ b/src/org/ibex/nestedvm/Runtime.java @@ -1,3 +1,7 @@ +// Copyright 2000-2005 the Contributors, as shown in the revision logs. +// Licensed under the Apache Public Source License 2.0 ("the License"). +// You may not use this file except in compliance with the License. + // Copyright 2003 Brian Alliet // Based on org.xwt.imp.MIPS by Adam Megacz // Portions Copyright 2003 Adam Megacz @@ -6,7 +10,6 @@ package org.ibex.nestedvm; import org.ibex.nestedvm.util.*; import java.io.*; -import java.util.Arrays; public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { public static final String VERSION = "1.0"; @@ -47,10 +50,10 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { /** When the process started */ private long startTime; - /** Text/Data loaded in memory */ - public final static int STOPPED = 0; /** Program is executing instructions */ - public final static int RUNNING = 1; + public final static int RUNNING = 0; // Horrible things will happen if this isn't 0 + /** Text/Data loaded in memory */ + public final static int STOPPED = 1; /** Prgram has been started but is paused */ public final static int PAUSED = 2; /** Program is executing a callJava() method */ @@ -71,8 +74,8 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { public ExecutionException exitException; /** Table containing all open file descriptors. (Entries are null if the fd is not in use */ - FD[] fds = new FD[OPEN_MAX]; // package-private for UnixRuntime - boolean closeOnExec[] = new boolean[OPEN_MAX]; + FD[] fds; // package-private for UnixRuntime + boolean closeOnExec[]; /** Pointer to a SecurityManager for this process */ SecurityManager sm; @@ -103,6 +106,16 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { /** Subclasses should set the CPUState to the state held in state */ protected abstract void setCPUState(CPUState state); + /** True to enabled a few hacks to better support the win32 console */ + final static boolean win32Hacks; + + static { + String os = Platform.getProperty("os.name"); + String prop = Platform.getProperty("nestedvm.win32hacks"); + if(prop != null) { win32Hacks = Boolean.valueOf(prop).booleanValue(); } + else { win32Hacks = os != null && os.toLowerCase().indexOf("windows") != -1; } + } + protected Object clone() throws CloneNotSupportedException { Runtime r = (Runtime) super.clone(); r._byteBuf = null; @@ -120,7 +133,8 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { return r; } - protected Runtime(int pageSize, int totalPages) { + protected Runtime(int pageSize, int totalPages) { this(pageSize, totalPages,false); } + protected Runtime(int pageSize, int totalPages, boolean exec) { if(pageSize <= 0) throw new IllegalArgumentException("pageSize <= 0"); if(totalPages <= 0) throw new IllegalArgumentException("totalPages <= 0"); if((pageSize&(pageSize-1)) != 0) throw new IllegalArgumentException("pageSize not a power of two"); @@ -158,11 +172,16 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { readPages[i] = writePages[i] = new int[pageSize>>2]; } } - - InputStream stdin = Boolean.valueOf(getSystemProperty("nestedvm.textstdin")).booleanValue() ? new TextInputStream(System.in) : System.in; - addFD(new TerminalFD(stdin)); - addFD(new TerminalFD(System.out)); - addFD(new TerminalFD(System.err)); + + if(!exec) { + fds = new FD[OPEN_MAX]; + closeOnExec = new boolean[OPEN_MAX]; + + InputStream stdin = win32Hacks ? new Win32ConsoleIS(System.in) : System.in; + addFD(new TerminalFD(stdin)); + addFD(new TerminalFD(System.out)); + addFD(new TerminalFD(System.err)); + } } /** Copy everything from src to addr initializing uninitialized pages if required. @@ -482,17 +501,16 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { } /** Calls _execute() (subclass's execute()) and catches exceptions */ - // FEATURE: Have these call kill() so we get a pretty message to stdout private void __execute() { try { _execute(); } catch(FaultException e) { if(STDERR_DIAG) e.printStackTrace(); - sys_exit(128+11); // SIGSEGV + exit(128+11,true); // SIGSEGV exitException = e; } catch(ExecutionException e) { if(STDERR_DIAG) e.printStackTrace(); - sys_exit(128+4); // SIGILL + exit(128+4,true); // SIGILL exitException = e; } } @@ -713,7 +731,6 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { if((flags & ~(3|O_CREAT|O_EXCL|O_APPEND|O_TRUNC)) != 0) { if(STDERR_DIAG) System.err.println("WARNING: Unsupported flags passed to open(\"" + f + "\"): " + toHex(flags & ~(3|O_CREAT|O_EXCL|O_APPEND|O_TRUNC))); - throw new ErrnoException(ENOTSUP); } boolean write = (flags&3) != RD_ONLY; @@ -722,7 +739,7 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { if((flags & (O_EXCL|O_CREAT)) == (O_EXCL|O_CREAT)) { try { - if(Platform.atomicCreateFile(f)) throw new ErrnoException(EEXIST); + if(!Platform.atomicCreateFile(f)) throw new ErrnoException(EEXIST); } catch(IOException e) { throw new ErrnoException(EIO); } @@ -732,10 +749,9 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { return hostFSDirFD(f,data); } - // FIXME: Truncate final Seekable.File sf; try { - sf = new Seekable.File(f,write); + sf = new Seekable.File(f,write,(flags & O_TRUNC) != 0); } catch(FileNotFoundException e) { if(e.getMessage() != null && e.getMessage().indexOf("Permission denied") >= 0) throw new ErrnoException(EACCES); return null; @@ -793,6 +809,17 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { copyout(buf,addr,n); return n; } + + /** The ftruncate syscall */ + private int sys_ftruncate(int fdn, long length) { + if (fdn < 0 || fdn >= OPEN_MAX) return -EBADFD; + if (fds[fdn] == null) return -EBADFD; + + Seekable seekable = fds[fdn].seekable(); + if (length < 0 || seekable == null) return -EINVAL; + try { seekable.resize(length); } catch (IOException e) { return -EIO; } + return 0; + } /** The close syscall */ private int sys_close(int fdn) { @@ -810,12 +837,11 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { } /** The stat/fstat syscall helper */ - // FIXME: Populate uid/gid/nlink int stat(FStat fs, int addr) throws FaultException { memWrite(addr+0,(fs.dev()<<16)|(fs.inode()&0xffff)); // st_dev (top 16), // st_ino (bottom 16) memWrite(addr+4,((fs.type()&0xf000))|(fs.mode()&0xfff)); // st_mode - memWrite(addr+8,1<<16); // st_nlink (top 16) // st_uid (bottom 16) - memWrite(addr+12,0); // st_gid (top 16) // st_rdev (bottom 16) + memWrite(addr+8,fs.nlink()<<16|fs.uid()&0xffff); // st_nlink (top 16) // st_uid (bottom 16) + memWrite(addr+12,fs.gid()<<16|0); // st_gid (top 16) // st_rdev (bottom 16) memWrite(addr+16,fs.size()); // st_size memWrite(addr+20,fs.atime()); // st_atime // memWrite(addr+24,0) // st_spare1 @@ -963,11 +989,21 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { /** Hook for subclasses to do something when the process exits */ void _exited() { } - private int sys_exit(int status) { + void exit(int status, boolean fromSignal) { + if(fromSignal && fds[2] != null) { + try { + byte[] msg = getBytes("Process exited on signal " + (status - 128) + "\n"); + fds[2].write(msg,0,msg.length); + } catch(ErrnoException e) { } + } exitStatus = status; for(int i=0;isyscall should be the contents of V0 and a, b, c, and d should be @@ -1006,9 +1042,11 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { protected final int syscall(int syscall, int a, int b, int c, int d, int e, int f) { try { int n = _syscall(syscall,a,b,c,d,e,f); - //if(n < 0) System.err.println("syscall: " + syscall + " returned " + n); + //if(n<0) throw new ErrnoException(-n); return n; } catch(ErrnoException ex) { + //System.err.println("While executing syscall: " + syscall + ":"); + //if(syscall == SYS_open) try { System.err.println("Failed to open " + cstring(a) + " errno " + ex.errno); } catch(Exception e2) { } //ex.printStackTrace(); return -ex.errno; } catch(FaultException ex) { @@ -1031,6 +1069,7 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { case SYS_close: return sys_close(a); case SYS_read: return sys_read(a,b,c); case SYS_lseek: return sys_lseek(a,b,c); + case SYS_ftruncate: return sys_ftruncate(a,b); case SYS_getpid: return sys_getpid(); case SYS_calljava: return sys_calljava(a,b,c,d); case SYS_gettimeofday: return sys_gettimeofday(a,b); @@ -1039,6 +1078,10 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { case SYS_getpagesize: return sys_getpagesize(); case SYS_fcntl: return sys_fcntl(a,b,c); case SYS_sysconf: return sys_sysconf(a); + case SYS_getuid: return sys_getuid(); + case SYS_geteuid: return sys_geteuid(); + case SYS_getgid: return sys_getgid(); + case SYS_getegid: return sys_getegid(); case SYS_memcpy: memcpy(a,b,c); return a; case SYS_memset: memset(a,b,c); return a; @@ -1060,6 +1103,11 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { } } + private int sys_getuid() { return 0; } + private int sys_geteuid() { return 0; } + private int sys_getgid() { return 0; } + private int sys_getegid() { return 0; } + public int xmalloc(int size) { int p=malloc(size); if(p==0) throw new RuntimeException("malloc() failed"); return p; } public int xrealloc(int addr,int newsize) { int p=realloc(addr,newsize); if(p==0) throw new RuntimeException("realloc() failed"); return p; } public int realloc(int addr, int newsize) { try { return call("realloc",addr,newsize); } catch(CallException e) { return 0; } } @@ -1112,8 +1160,6 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { public int getdents(byte[] a, int off, int length) throws ErrnoException { throw new ErrnoException(EBADFD); } - public int flags() { return O_RDONLY; } - /** Return a Seekable object representing this file descriptor (can be read only) This is required for exec() */ Seekable seekable() { return null; } @@ -1125,6 +1171,7 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { } protected abstract FStat _fstat(); + public abstract int flags(); /** Closes the fd */ public final void close() { if(--refCount==0) _close(); } @@ -1228,7 +1275,7 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { } } - public FStat _fstat() { return new FStat(); } + public FStat _fstat() { return new SocketFStat(); } } static class TerminalFD extends InputOutputStreamFD { @@ -1236,14 +1283,14 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { public TerminalFD(OutputStream os) { this(null,os); } public TerminalFD(InputStream is, OutputStream os) { super(is,os); } public void _close() { /* noop */ } - public FStat _fstat() { return new FStat() { public int type() { return S_IFCHR; } }; } + public FStat _fstat() { return new SocketFStat() { public int type() { return S_IFCHR; } public int mode() { return 0600; } }; } } - // FEATURE: TextInputStream: This is pretty inefficient but it is only used for reading from the console on win32 - static class TextInputStream extends InputStream { + // This is pretty inefficient but it is only used for reading from the console on win32 + static class Win32ConsoleIS extends InputStream { private int pushedBack = -1; private final InputStream parent; - public TextInputStream(InputStream parent) { this.parent = parent; } + public Win32ConsoleIS(InputStream parent) { this.parent = parent; } public int read() throws IOException { if(pushedBack != -1) { int c = pushedBack; pushedBack = -1; return c; } int c = parent.read(); @@ -1258,7 +1305,7 @@ public abstract class Runtime implements UsermodeConstants,Registers,Cloneable { pos++; len--; pb = true; } int n = parent.read(buf,pos,len); - if(n == -1) return -1; + if(n == -1) return pb ? 1 : -1; for(int i=0;i