SysCalls: Implement truncate64 system call
[gem5.git] / src / sim / syscall_emul.hh
index b21e299e99bb9d240ceb3f3aa213b5ba601c8906..27c26afb0f08714bf015cf33b0a54fdf2cddc3b0 100644 (file)
@@ -32,8 +32,8 @@
 #ifndef __SIM_SYSCALL_EMUL_HH__
 #define __SIM_SYSCALL_EMUL_HH__
 
-#define BSD_HOST (defined(__APPLE__) || defined(__OpenBSD__) || \
-                  defined(__FreeBSD__))
+#define NO_STAT64 (defined(__APPLE__) || defined(__OpenBSD__) || \
+                   defined(__FreeBSD__) || defined(__CYGWIN__))
 
 ///
 /// @file syscall_emul.hh
 #include <errno.h>
 #include <string>
 #ifdef __CYGWIN32__
-#include <sys/fcntl.h> // for O_BINARY
+#include <sys/fcntl.h>  // for O_BINARY
 #endif
+#include <sys/stat.h>
+#include <fcntl.h>
 #include <sys/uio.h>
 
-#include "arch/isa_traits.hh"  // for Addr
 #include "base/chunk_generator.hh"
-#include "base/intmath.hh"     // for RoundUp
+#include "base/intmath.hh"      // for RoundUp
 #include "base/misc.hh"
 #include "base/trace.hh"
+#include "base/types.hh"
+#include "config/the_isa.hh"
 #include "cpu/base.hh"
-#include "cpu/exec_context.hh"
+#include "cpu/thread_context.hh"
 #include "mem/translating_port.hh"
 #include "mem/page_table.hh"
+#include "sim/system.hh"
 #include "sim/process.hh"
 
 ///
@@ -68,17 +72,17 @@ class SyscallDesc {
 
     /// Typedef for target syscall handler functions.
     typedef SyscallReturn (*FuncPtr)(SyscallDesc *, int num,
-                           Process *, ExecContext *);
+                           LiveProcess *, ThreadContext *);
 
-    const char *name;  //!< Syscall name (e.g., "open").
-    FuncPtr funcPtr;   //!< Pointer to emulation function.
-    int flags;         //!< Flags (see Flags enum).
+    const char *name;   //!< Syscall name (e.g., "open").
+    FuncPtr funcPtr;    //!< Pointer to emulation function.
+    int flags;          //!< Flags (see Flags enum).
 
     /// Flag values for controlling syscall behavior.
     enum Flags {
         /// Don't set return regs according to funcPtr return value.
         /// Used for syscalls with non-standard return conventions
-        /// that explicitly set the ExecContext regs (e.g.,
+        /// that explicitly set the ThreadContext regs (e.g.,
         /// sigreturn).
         SuppressReturnValue = 1
     };
@@ -90,7 +94,7 @@ class SyscallDesc {
     }
 
     /// Emulate the syscall.  Public interface for calling through funcPtr.
-    void doSyscall(int callnum, Process *proc, ExecContext *xc);
+    void doSyscall(int callnum, LiveProcess *proc, ThreadContext *tc);
 };
 
 
@@ -115,7 +119,7 @@ class BaseBufferArg {
     virtual bool copyIn(TranslatingPort *memport)
     {
         memport->readBlob(addr, bufPtr, size);
-        return true;   // no EFAULT detection for now
+        return true;    // no EFAULT detection for now
     }
 
     //
@@ -124,7 +128,7 @@ class BaseBufferArg {
     virtual bool copyOut(TranslatingPort *memport)
     {
         memport->writeBlob(addr, bufPtr, size);
-        return true;   // no EFAULT detection for now
+        return true;    // no EFAULT detection for now
     }
 
   protected:
@@ -138,7 +142,7 @@ class BufferArg : public BaseBufferArg
 {
   public:
     BufferArg(Addr _addr, int _size) : BaseBufferArg(_addr, _size) { }
-    void *bufferPtr()  { return bufPtr; }
+    void *bufferPtr()   { return bufPtr; }
 };
 
 template <class T>
@@ -156,8 +160,8 @@ class TypedBufferArg : public BaseBufferArg
     operator T*() { return (T *)bufPtr; }
 
     // dereference operators
-    T &operator*()      { return *((T *)bufPtr); }
-    T* operator->()     { return (T *)bufPtr; }
+    T &operator*()       { return *((T *)bufPtr); }
+    T* operator->()      { return (T *)bufPtr; }
     T &operator[](int i) { return ((T *)bufPtr)[i]; }
 };
 
@@ -172,138 +176,174 @@ class TypedBufferArg : public BaseBufferArg
 
 /// Handler for unimplemented syscalls that we haven't thought about.
 SyscallReturn unimplementedFunc(SyscallDesc *desc, int num,
-                                Process *p, ExecContext *xc);
+                                LiveProcess *p, ThreadContext *tc);
 
 /// Handler for unimplemented syscalls that we never intend to
 /// implement (signal handling, etc.) and should not affect the correct
 /// behavior of the program.  Print a warning only if the appropriate
 /// trace flag is enabled.  Return success to the target program.
 SyscallReturn ignoreFunc(SyscallDesc *desc, int num,
-                         Process *p, ExecContext *xc);
+                         LiveProcess *p, ThreadContext *tc);
 
-/// Target exit() handler: terminate simulation.
+/// Target exit() handler: terminate current context.
 SyscallReturn exitFunc(SyscallDesc *desc, int num,
-                       Process *p, ExecContext *xc);
+                       LiveProcess *p, ThreadContext *tc);
+
+/// Target exit_group() handler: terminate simulation. (exit all threads)
+SyscallReturn exitGroupFunc(SyscallDesc *desc, int num,
+                       LiveProcess *p, ThreadContext *tc);
 
 /// Target getpagesize() handler.
 SyscallReturn getpagesizeFunc(SyscallDesc *desc, int num,
-                              Process *p, ExecContext *xc);
+                              LiveProcess *p, ThreadContext *tc);
 
-/// Target obreak() handler: set brk address.
-SyscallReturn obreakFunc(SyscallDesc *desc, int num,
-                         Process *p, ExecContext *xc);
+/// Target brk() handler: set brk address.
+SyscallReturn brkFunc(SyscallDesc *desc, int num,
+                      LiveProcess *p, ThreadContext *tc);
 
 /// Target close() handler.
 SyscallReturn closeFunc(SyscallDesc *desc, int num,
-                        Process *p, ExecContext *xc);
+                        LiveProcess *p, ThreadContext *tc);
 
 /// Target read() handler.
 SyscallReturn readFunc(SyscallDesc *desc, int num,
-                       Process *p, ExecContext *xc);
+                       LiveProcess *p, ThreadContext *tc);
 
 /// Target write() handler.
 SyscallReturn writeFunc(SyscallDesc *desc, int num,
-                        Process *p, ExecContext *xc);
+                        LiveProcess *p, ThreadContext *tc);
 
 /// Target lseek() handler.
 SyscallReturn lseekFunc(SyscallDesc *desc, int num,
-                        Process *p, ExecContext *xc);
+                        LiveProcess *p, ThreadContext *tc);
+
+/// Target _llseek() handler.
+SyscallReturn _llseekFunc(SyscallDesc *desc, int num,
+                        LiveProcess *p, ThreadContext *tc);
 
 /// Target munmap() handler.
 SyscallReturn munmapFunc(SyscallDesc *desc, int num,
-                         Process *p, ExecContext *xc);
+                         LiveProcess *p, ThreadContext *tc);
 
 /// Target gethostname() handler.
 SyscallReturn gethostnameFunc(SyscallDesc *desc, int num,
-                              Process *p, ExecContext *xc);
+                              LiveProcess *p, ThreadContext *tc);
+
+/// Target getcwd() handler.
+SyscallReturn getcwdFunc(SyscallDesc *desc, int num,
+                         LiveProcess *p, ThreadContext *tc);
+
+/// Target unlink() handler.
+SyscallReturn readlinkFunc(SyscallDesc *desc, int num,
+                           LiveProcess *p, ThreadContext *tc);
 
 /// Target unlink() handler.
 SyscallReturn unlinkFunc(SyscallDesc *desc, int num,
-                         Process *p, ExecContext *xc);
+                         LiveProcess *p, ThreadContext *tc);
+
+/// Target mkdir() handler.
+SyscallReturn mkdirFunc(SyscallDesc *desc, int num,
+                        LiveProcess *p, ThreadContext *tc);
 
 /// Target rename() handler.
 SyscallReturn renameFunc(SyscallDesc *desc, int num,
-                         Process *p, ExecContext *xc);
+                         LiveProcess *p, ThreadContext *tc);
 
 
 /// Target truncate() handler.
 SyscallReturn truncateFunc(SyscallDesc *desc, int num,
-                           Process *p, ExecContext *xc);
+                           LiveProcess *p, ThreadContext *tc);
 
 
 /// Target ftruncate() handler.
 SyscallReturn ftruncateFunc(SyscallDesc *desc, int num,
-                            Process *p, ExecContext *xc);
+                            LiveProcess *p, ThreadContext *tc);
+
+
+/// Target truncate64() handler.
+SyscallReturn truncate64Func(SyscallDesc *desc, int num,
+                             LiveProcess *p, ThreadContext *tc);
+
+/// Target ftruncate64() handler.
+SyscallReturn ftruncate64Func(SyscallDesc *desc, int num,
+                              LiveProcess *p, ThreadContext *tc);
+
+
+/// Target umask() handler.
+SyscallReturn umaskFunc(SyscallDesc *desc, int num,
+                        LiveProcess *p, ThreadContext *tc);
 
 
 /// Target chown() handler.
 SyscallReturn chownFunc(SyscallDesc *desc, int num,
-                        Process *p, ExecContext *xc);
+                        LiveProcess *p, ThreadContext *tc);
 
 
 /// Target fchown() handler.
 SyscallReturn fchownFunc(SyscallDesc *desc, int num,
-                         Process *p, ExecContext *xc);
+                         LiveProcess *p, ThreadContext *tc);
+
+/// Target dup() handler.
+SyscallReturn dupFunc(SyscallDesc *desc, int num,
+                      LiveProcess *process, ThreadContext *tc);
 
 /// Target fnctl() handler.
 SyscallReturn fcntlFunc(SyscallDesc *desc, int num,
-                        Process *process, ExecContext *xc);
+                        LiveProcess *process, ThreadContext *tc);
+
+/// Target fcntl64() handler.
+SyscallReturn fcntl64Func(SyscallDesc *desc, int num,
+                        LiveProcess *process, ThreadContext *tc);
 
 /// Target setuid() handler.
 SyscallReturn setuidFunc(SyscallDesc *desc, int num,
-                               Process *p, ExecContext *xc);
+                               LiveProcess *p, ThreadContext *tc);
 
 /// Target getpid() handler.
 SyscallReturn getpidFunc(SyscallDesc *desc, int num,
-                               Process *p, ExecContext *xc);
+                               LiveProcess *p, ThreadContext *tc);
 
 /// Target getuid() handler.
 SyscallReturn getuidFunc(SyscallDesc *desc, int num,
-                               Process *p, ExecContext *xc);
+                               LiveProcess *p, ThreadContext *tc);
 
 /// Target getgid() handler.
 SyscallReturn getgidFunc(SyscallDesc *desc, int num,
-                               Process *p, ExecContext *xc);
+                               LiveProcess *p, ThreadContext *tc);
 
 /// Target getppid() handler.
 SyscallReturn getppidFunc(SyscallDesc *desc, int num,
-                               Process *p, ExecContext *xc);
+                               LiveProcess *p, ThreadContext *tc);
 
 /// Target geteuid() handler.
 SyscallReturn geteuidFunc(SyscallDesc *desc, int num,
-                               Process *p, ExecContext *xc);
+                               LiveProcess *p, ThreadContext *tc);
 
 /// Target getegid() handler.
 SyscallReturn getegidFunc(SyscallDesc *desc, int num,
-                               Process *p, ExecContext *xc);
+                               LiveProcess *p, ThreadContext *tc);
 
+/// Target clone() handler.
+SyscallReturn cloneFunc(SyscallDesc *desc, int num,
+                               LiveProcess *p, ThreadContext *tc);
 
 
 /// Pseudo Funcs  - These functions use a different return convension,
 /// returning a second value in a register other than the normal return register
 SyscallReturn pipePseudoFunc(SyscallDesc *desc, int num,
-                             Process *process, ExecContext *xc);
+                             LiveProcess *process, ThreadContext *tc);
 
 /// Target getpidPseudo() handler.
 SyscallReturn getpidPseudoFunc(SyscallDesc *desc, int num,
-                               Process *p, ExecContext *xc);
+                               LiveProcess *p, ThreadContext *tc);
 
 /// Target getuidPseudo() handler.
 SyscallReturn getuidPseudoFunc(SyscallDesc *desc, int num,
-                               Process *p, ExecContext *xc);
+                               LiveProcess *p, ThreadContext *tc);
 
 /// Target getgidPseudo() handler.
 SyscallReturn getgidPseudoFunc(SyscallDesc *desc, int num,
-                               Process *p, ExecContext *xc);
-
-
-/// This struct is used to build an target-OS-dependent table that
-/// maps the target's open() flags to the host open() flags.
-struct OpenFlagTransTable {
-    int tgtFlag;       //!< Target system flag value.
-    int hostFlag;      //!< Corresponding host system flag value.
-};
-
+                               LiveProcess *p, ThreadContext *tc);
 
 
 /// A readable name for 1,000,000, for converting microseconds to seconds.
@@ -332,16 +372,122 @@ getElapsedTime(T1 &sec, T2 &usec)
 //
 //////////////////////////////////////////////////////////////////////
 
+#if NO_STAT64
+    typedef struct stat hst_stat;
+    typedef struct stat hst_stat64;
+#else
+    typedef struct stat hst_stat;
+    typedef struct stat64 hst_stat64;
+#endif
+
+//// Helper function to convert a host stat buffer to a target stat
+//// buffer.  Also copies the target buffer out to the simulated
+//// memory space.  Used by stat(), fstat(), and lstat().
+
+template <typename target_stat, typename host_stat>
+static void
+convertStatBuf(target_stat &tgt, host_stat *host, bool fakeTTY = false)
+{
+    using namespace TheISA;
+
+    if (fakeTTY)
+        tgt->st_dev = 0xA;
+    else
+        tgt->st_dev = host->st_dev;
+    tgt->st_dev = htog(tgt->st_dev);
+    tgt->st_ino = host->st_ino;
+    tgt->st_ino = htog(tgt->st_ino);
+    tgt->st_mode = host->st_mode;
+    if (fakeTTY) {
+        // Claim to be a character device
+        tgt->st_mode &= ~S_IFMT;    // Clear S_IFMT
+        tgt->st_mode |= S_IFCHR;    // Set S_IFCHR
+    }
+    tgt->st_mode = htog(tgt->st_mode);
+    tgt->st_nlink = host->st_nlink;
+    tgt->st_nlink = htog(tgt->st_nlink);
+    tgt->st_uid = host->st_uid;
+    tgt->st_uid = htog(tgt->st_uid);
+    tgt->st_gid = host->st_gid;
+    tgt->st_gid = htog(tgt->st_gid);
+    if (fakeTTY)
+        tgt->st_rdev = 0x880d;
+    else
+        tgt->st_rdev = host->st_rdev;
+    tgt->st_rdev = htog(tgt->st_rdev);
+    tgt->st_size = host->st_size;
+    tgt->st_size = htog(tgt->st_size);
+    tgt->st_atimeX = host->st_atime;
+    tgt->st_atimeX = htog(tgt->st_atimeX);
+    tgt->st_mtimeX = host->st_mtime;
+    tgt->st_mtimeX = htog(tgt->st_mtimeX);
+    tgt->st_ctimeX = host->st_ctime;
+    tgt->st_ctimeX = htog(tgt->st_ctimeX);
+    // Force the block size to be 8k. This helps to ensure buffered io works
+    // consistently across different hosts.
+    tgt->st_blksize = 0x2000;
+    tgt->st_blksize = htog(tgt->st_blksize);
+    tgt->st_blocks = host->st_blocks;
+    tgt->st_blocks = htog(tgt->st_blocks);
+}
+
+// Same for stat64
+
+template <typename target_stat, typename host_stat64>
+static void
+convertStat64Buf(target_stat &tgt, host_stat64 *host, bool fakeTTY = false)
+{
+    using namespace TheISA;
+
+    convertStatBuf<target_stat, host_stat64>(tgt, host, fakeTTY);
+#if defined(STAT_HAVE_NSEC)
+    tgt->st_atime_nsec = host->st_atime_nsec;
+    tgt->st_atime_nsec = htog(tgt->st_atime_nsec);
+    tgt->st_mtime_nsec = host->st_mtime_nsec;
+    tgt->st_mtime_nsec = htog(tgt->st_mtime_nsec);
+    tgt->st_ctime_nsec = host->st_ctime_nsec;
+    tgt->st_ctime_nsec = htog(tgt->st_ctime_nsec);
+#else
+    tgt->st_atime_nsec = 0;
+    tgt->st_mtime_nsec = 0;
+    tgt->st_ctime_nsec = 0;
+#endif
+}
+
+//Here are a couple convenience functions
+template<class OS>
+static void
+copyOutStatBuf(TranslatingPort * mem, Addr addr,
+        hst_stat *host, bool fakeTTY = false)
+{
+    typedef TypedBufferArg<typename OS::tgt_stat> tgt_stat_buf;
+    tgt_stat_buf tgt(addr);
+    convertStatBuf<tgt_stat_buf, hst_stat>(tgt, host, fakeTTY);
+    tgt.copyOut(mem);
+}
+
+template<class OS>
+static void
+copyOutStat64Buf(TranslatingPort * mem, Addr addr,
+        hst_stat64 *host, bool fakeTTY = false)
+{
+    typedef TypedBufferArg<typename OS::tgt_stat64> tgt_stat_buf;
+    tgt_stat_buf tgt(addr);
+    convertStat64Buf<tgt_stat_buf, hst_stat64>(tgt, host, fakeTTY);
+    tgt.copyOut(mem);
+}
+
 /// Target ioctl() handler.  For the most part, programs call ioctl()
 /// only to find out if their stdout is a tty, to determine whether to
 /// do line or block buffering.
 template <class OS>
 SyscallReturn
-ioctlFunc(SyscallDesc *desc, int callnum, Process *process,
-          ExecContext *xc)
+ioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+          ThreadContext *tc)
 {
-    int fd = xc->getSyscallArg(0);
-    unsigned req = xc->getSyscallArg(1);
+    int index = 0;
+    int fd = process->getSyscallArg(tc, index);
+    unsigned req = process->getSyscallArg(tc, index);
 
     DPRINTF(SyscallVerbose, "ioctl(%d, 0x%x, ...)\n", fd, req);
 
@@ -351,31 +497,34 @@ ioctlFunc(SyscallDesc *desc, int callnum, Process *process,
     }
 
     switch (req) {
-      case OS::TIOCISATTY:
-      case OS::TIOCGETP:
-      case OS::TIOCSETP:
-      case OS::TIOCSETN:
-      case OS::TIOCSETC:
-      case OS::TIOCGETC:
-      case OS::TIOCGETS:
-      case OS::TIOCGETA:
+      case OS::TIOCISATTY_:
+      case OS::TIOCGETP_:
+      case OS::TIOCSETP_:
+      case OS::TIOCSETN_:
+      case OS::TIOCSETC_:
+      case OS::TIOCGETC_:
+      case OS::TIOCGETS_:
+      case OS::TIOCGETA_:
+      case OS::TCSETAW_:
         return -ENOTTY;
 
       default:
         fatal("Unsupported ioctl call: ioctl(%d, 0x%x, ...) @ 0x%llx\n",
-              fd, req, xc->readPC());
+              fd, req, tc->readPC());
     }
 }
 
 /// Target open() handler.
 template <class OS>
 SyscallReturn
-openFunc(SyscallDesc *desc, int callnum, Process *process,
-         ExecContext *xc)
+openFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+         ThreadContext *tc)
 {
     std::string path;
 
-    if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
+    int index = 0;
+    if (!tc->getMemPort()->tryReadString(path,
+                process->getSyscallArg(tc, index)))
         return -EFAULT;
 
     if (path == "/dev/sysdev0") {
@@ -385,8 +534,8 @@ openFunc(SyscallDesc *desc, int callnum, Process *process,
         return -ENOENT;
     }
 
-    int tgtFlags = xc->getSyscallArg(1);
-    int mode = xc->getSyscallArg(2);
+    int tgtFlags = process->getSyscallArg(tc, index);
+    int mode = process->getSyscallArg(tc, index);
     int hostFlags = 0;
 
     // translate open flags
@@ -405,32 +554,67 @@ openFunc(SyscallDesc *desc, int callnum, Process *process,
     hostFlags |= O_BINARY;
 #endif
 
+    // Adjust path for current working directory
+    path = process->fullPath(path);
+
     DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str());
 
-    // open the file
-    int fd = open(path.c_str(), hostFlags, mode);
+    int fd;
+    if (!path.compare(0, 6, "/proc/") || !path.compare(0, 8, "/system/") ||
+        !path.compare(0, 10, "/platform/") || !path.compare(0, 5, "/sys/")) {
+        // It's a proc/sys entery and requires special handling
+        fd = OS::openSpecialFile(path, process, tc);
+        return (fd == -1) ? -1 : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false);
+     } else {
+        // open the file
+        fd = open(path.c_str(), hostFlags, mode);
+        return (fd == -1) ? -errno : process->alloc_fd(fd,path.c_str(),hostFlags,mode, false);
+     }
 
-    return (fd == -1) ? -errno : process->alloc_fd(fd);
 }
 
+/// Target sysinfo() handler.
+template <class OS>
+SyscallReturn
+sysinfoFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+         ThreadContext *tc)
+{
+
+    int index = 0;
+    TypedBufferArg<typename OS::tgt_sysinfo>
+        sysinfo(process->getSyscallArg(tc, index));   
+
+    sysinfo->uptime=seconds_since_epoch;
+    sysinfo->totalram=process->system->memSize();
+
+    sysinfo.copyOut(tc->getMemPort());
+
+    return 0;
+}
 
 /// Target chmod() handler.
 template <class OS>
 SyscallReturn
-chmodFunc(SyscallDesc *desc, int callnum, Process *process,
-          ExecContext *xc)
+chmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+          ThreadContext *tc)
 {
     std::string path;
 
-    if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
+    int index = 0;
+    if (!tc->getMemPort()->tryReadString(path,
+                process->getSyscallArg(tc, index))) {
         return -EFAULT;
+    }
 
-    uint32_t mode = xc->getSyscallArg(1);
+    uint32_t mode = process->getSyscallArg(tc, index);
     mode_t hostMode = 0;
 
     // XXX translate mode flags via OS::something???
     hostMode = mode;
 
+    // Adjust path for current working directory
+    path = process->fullPath(path);
+
     // do the chmod
     int result = chmod(path.c_str(), hostMode);
     if (result < 0)
@@ -443,16 +627,17 @@ chmodFunc(SyscallDesc *desc, int callnum, Process *process,
 /// Target fchmod() handler.
 template <class OS>
 SyscallReturn
-fchmodFunc(SyscallDesc *desc, int callnum, Process *process,
-           ExecContext *xc)
+fchmodFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+           ThreadContext *tc)
 {
-    int fd = xc->getSyscallArg(0);
+    int index = 0;
+    int fd = process->getSyscallArg(tc, index);
     if (fd < 0 || process->sim_fd(fd) < 0) {
         // doesn't map to any simulator fd: not a valid target fd
         return -EBADF;
     }
 
-    uint32_t mode = xc->getSyscallArg(1);
+    uint32_t mode = process->getSyscallArg(tc, index);
     mode_t hostMode = 0;
 
     // XXX translate mode flags via OS::someting???
@@ -466,17 +651,70 @@ fchmodFunc(SyscallDesc *desc, int callnum, Process *process,
     return 0;
 }
 
+/// Target mremap() handler.
+template <class OS>
+SyscallReturn
+mremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc)
+{
+    int index = 0;
+    Addr start = process->getSyscallArg(tc, index);
+    uint64_t old_length = process->getSyscallArg(tc, index);
+    uint64_t new_length = process->getSyscallArg(tc, index);
+    uint64_t flags = process->getSyscallArg(tc, index);
+
+    if ((start % TheISA::VMPageSize != 0) ||
+            (new_length % TheISA::VMPageSize != 0)) {
+        warn("mremap failing: arguments not page aligned");
+        return -EINVAL;
+    }
+
+    if (new_length > old_length) {
+        if ((start + old_length) == process->mmap_end) {
+            uint64_t diff = new_length - old_length;
+            process->pTable->allocate(process->mmap_end, diff);
+            process->mmap_end += diff;
+            return start;
+        } else {
+            // sys/mman.h defined MREMAP_MAYMOVE
+            if (!(flags & 1)) {
+                warn("can't remap here and MREMAP_MAYMOVE flag not set\n");
+                return -ENOMEM;
+            } else {
+                process->pTable->remap(start, old_length, process->mmap_end);
+                warn("mremapping to totally new vaddr %08p-%08p, adding %d\n", 
+                        process->mmap_end, process->mmap_end + new_length, new_length);
+                start = process->mmap_end;
+                // add on the remaining unallocated pages
+                process->pTable->allocate(start + old_length, new_length - old_length);
+                process->mmap_end += new_length;
+                warn("returning %08p as start\n", start);
+                return start;
+            }
+        }
+    } else {
+        process->pTable->deallocate(start + new_length, old_length -
+                new_length);
+        return start;
+    }
+}
 
 /// Target stat() handler.
 template <class OS>
 SyscallReturn
-statFunc(SyscallDesc *desc, int callnum, Process *process,
-         ExecContext *xc)
+statFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+         ThreadContext *tc)
 {
     std::string path;
 
-    if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
-    return -EFAULT;
+    int index = 0;
+    if (!tc->getMemPort()->tryReadString(path,
+                process->getSyscallArg(tc, index))) {
+        return -EFAULT;
+    }
+    Addr bufPtr = process->getSyscallArg(tc, index);
+
+    // Adjust path for current working directory
+    path = process->fullPath(path);
 
     struct stat hostBuf;
     int result = stat(path.c_str(), &hostBuf);
@@ -484,7 +722,41 @@ statFunc(SyscallDesc *desc, int callnum, Process *process,
     if (result < 0)
         return -errno;
 
-    OS::copyOutStatBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf);
+    copyOutStatBuf<OS>(tc->getMemPort(), bufPtr, &hostBuf);
+
+    return 0;
+}
+
+
+/// Target stat64() handler.
+template <class OS>
+SyscallReturn
+stat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
+           ThreadContext *tc)
+{
+    std::string path;
+
+    int index = 0;
+    if (!tc->getMemPort()->tryReadString(path,
+                process->getSyscallArg(tc, index)))
+        return -EFAULT;
+    Addr bufPtr = process->getSyscallArg(tc, index);
+
+    // Adjust path for current working directory
+    path = process->fullPath(path);
+
+#if NO_STAT64
+    struct stat  hostBuf;
+    int result = stat(path.c_str(), &hostBuf);
+#else
+    struct stat64 hostBuf;
+    int result = stat64(path.c_str(), &hostBuf);
+#endif
+
+    if (result < 0)
+        return -errno;
+
+    copyOutStat64Buf<OS>(tc->getMemPort(), bufPtr, &hostBuf);
 
     return 0;
 }
@@ -493,16 +765,18 @@ statFunc(SyscallDesc *desc, int callnum, Process *process,
 /// Target fstat64() handler.
 template <class OS>
 SyscallReturn
-fstat64Func(SyscallDesc *desc, int callnum, Process *process,
-            ExecContext *xc)
+fstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
+            ThreadContext *tc)
 {
-    int fd = xc->getSyscallArg(0);
+    int index = 0;
+    int fd = process->getSyscallArg(tc, index);
+    Addr bufPtr = process->getSyscallArg(tc, index);
     if (fd < 0 || process->sim_fd(fd) < 0) {
         // doesn't map to any simulator fd: not a valid target fd
         return -EBADF;
     }
 
-#if BSD_HOST
+#if NO_STAT64
     struct stat  hostBuf;
     int result = fstat(process->sim_fd(fd), &hostBuf);
 #else
@@ -513,7 +787,7 @@ fstat64Func(SyscallDesc *desc, int callnum, Process *process,
     if (result < 0)
         return -errno;
 
-    OS::copyOutStat64Buf(xc->getMemPort(), fd, xc->getSyscallArg(1), &hostBuf);
+    copyOutStat64Buf<OS>(tc->getMemPort(), bufPtr, &hostBuf, (fd == 1));
 
     return 0;
 }
@@ -522,13 +796,20 @@ fstat64Func(SyscallDesc *desc, int callnum, Process *process,
 /// Target lstat() handler.
 template <class OS>
 SyscallReturn
-lstatFunc(SyscallDesc *desc, int callnum, Process *process,
-          ExecContext *xc)
+lstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+          ThreadContext *tc)
 {
     std::string path;
 
-    if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
-      return -EFAULT;
+    int index = 0;
+    if (!tc->getMemPort()->tryReadString(path,
+                process->getSyscallArg(tc, index))) {
+        return -EFAULT;
+    }
+    Addr bufPtr = process->getSyscallArg(tc, index);
+
+    // Adjust path for current working directory
+    path = process->fullPath(path);
 
     struct stat hostBuf;
     int result = lstat(path.c_str(), &hostBuf);
@@ -536,7 +817,7 @@ lstatFunc(SyscallDesc *desc, int callnum, Process *process,
     if (result < 0)
         return -errno;
 
-    OS::copyOutStatBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf);
+    copyOutStatBuf<OS>(tc->getMemPort(), bufPtr, &hostBuf);
 
     return 0;
 }
@@ -544,15 +825,22 @@ lstatFunc(SyscallDesc *desc, int callnum, Process *process,
 /// Target lstat64() handler.
 template <class OS>
 SyscallReturn
-lstat64Func(SyscallDesc *desc, int callnum, Process *process,
-            ExecContext *xc)
+lstat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
+            ThreadContext *tc)
 {
     std::string path;
 
-    if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
-      return -EFAULT;
+    int index = 0;
+    if (!tc->getMemPort()->tryReadString(path,
+                process->getSyscallArg(tc, index))) {
+        return -EFAULT;
+    }
+    Addr bufPtr = process->getSyscallArg(tc, index);
+
+    // Adjust path for current working directory
+    path = process->fullPath(path);
 
-#if BSD_HOST
+#if NO_STAT64
     struct stat hostBuf;
     int result = lstat(path.c_str(), &hostBuf);
 #else
@@ -563,7 +851,7 @@ lstat64Func(SyscallDesc *desc, int callnum, Process *process,
     if (result < 0)
         return -errno;
 
-    OS::copyOutStat64Buf(xc->getMemPort(), -1, xc->getSyscallArg(1), &hostBuf);
+    copyOutStat64Buf<OS>(tc->getMemPort(), bufPtr, &hostBuf);
 
     return 0;
 }
@@ -571,10 +859,12 @@ lstat64Func(SyscallDesc *desc, int callnum, Process *process,
 /// Target fstat() handler.
 template <class OS>
 SyscallReturn
-fstatFunc(SyscallDesc *desc, int callnum, Process *process,
-          ExecContext *xc)
+fstatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+          ThreadContext *tc)
 {
-    int fd = process->sim_fd(xc->getSyscallArg(0));
+    int index = 0;
+    int fd = process->sim_fd(process->getSyscallArg(tc, index));
+    Addr bufPtr = process->getSyscallArg(tc, index);
 
     DPRINTF(SyscallVerbose, "fstat(%d, ...)\n", fd);
 
@@ -587,7 +877,7 @@ fstatFunc(SyscallDesc *desc, int callnum, Process *process,
     if (result < 0)
         return -errno;
 
-    OS::copyOutStatBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf);
+    copyOutStatBuf<OS>(tc->getMemPort(), bufPtr, &hostBuf, (fd == 1));
 
     return 0;
 }
@@ -596,13 +886,20 @@ fstatFunc(SyscallDesc *desc, int callnum, Process *process,
 /// Target statfs() handler.
 template <class OS>
 SyscallReturn
-statfsFunc(SyscallDesc *desc, int callnum, Process *process,
-           ExecContext *xc)
+statfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+           ThreadContext *tc)
 {
     std::string path;
 
-    if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
-      return -EFAULT;
+    int index = 0;
+    if (!tc->getMemPort()->tryReadString(path,
+                process->getSyscallArg(tc, index))) {
+        return -EFAULT;
+    }
+    Addr bufPtr = process->getSyscallArg(tc, index);
+
+    // Adjust path for current working directory
+    path = process->fullPath(path);
 
     struct statfs hostBuf;
     int result = statfs(path.c_str(), &hostBuf);
@@ -610,7 +907,7 @@ statfsFunc(SyscallDesc *desc, int callnum, Process *process,
     if (result < 0)
         return -errno;
 
-    OS::copyOutStatfsBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf);
+    OS::copyOutStatfsBuf(tc->getMemPort(), bufPtr, &hostBuf);
 
     return 0;
 }
@@ -619,10 +916,12 @@ statfsFunc(SyscallDesc *desc, int callnum, Process *process,
 /// Target fstatfs() handler.
 template <class OS>
 SyscallReturn
-fstatfsFunc(SyscallDesc *desc, int callnum, Process *process,
-            ExecContext *xc)
+fstatfsFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+            ThreadContext *tc)
 {
-    int fd = process->sim_fd(xc->getSyscallArg(0));
+    int index = 0;
+    int fd = process->sim_fd(process->getSyscallArg(tc, index));
+    Addr bufPtr = process->getSyscallArg(tc, index);
 
     if (fd < 0)
         return -EBADF;
@@ -633,7 +932,7 @@ fstatfsFunc(SyscallDesc *desc, int callnum, Process *process,
     if (result < 0)
         return -errno;
 
-    OS::copyOutStatfsBuf(xc->getMemPort(), xc->getSyscallArg(1), &hostBuf);
+    OS::copyOutStatfsBuf(tc->getMemPort(), bufPtr, &hostBuf);
 
     return 0;
 }
@@ -642,21 +941,21 @@ fstatfsFunc(SyscallDesc *desc, int callnum, Process *process,
 /// Target writev() handler.
 template <class OS>
 SyscallReturn
-writevFunc(SyscallDesc *desc, int callnum, Process *process,
-           ExecContext *xc)
+writevFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+           ThreadContext *tc)
 {
-    int fd = xc->getSyscallArg(0);
+    int index = 0;
+    int fd = process->getSyscallArg(tc, index);
     if (fd < 0 || process->sim_fd(fd) < 0) {
         // doesn't map to any simulator fd: not a valid target fd
         return -EBADF;
     }
 
-    TranslatingPort *p = xc->getMemPort();
-    uint64_t tiov_base = xc->getSyscallArg(1);
-    size_t count = xc->getSyscallArg(2);
+    TranslatingPort *p = tc->getMemPort();
+    uint64_t tiov_base = process->getSyscallArg(tc, index);
+    size_t count = process->getSyscallArg(tc, index);
     struct iovec hiov[count];
-    for (int i = 0; i < count; ++i)
-    {
+    for (size_t i = 0; i < count; ++i) {
         typename OS::tgt_iovec tiov;
 
         p->readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec),
@@ -669,10 +968,8 @@ writevFunc(SyscallDesc *desc, int callnum, Process *process,
 
     int result = writev(process->sim_fd(fd), hiov, count);
 
-    for (int i = 0; i < count; ++i)
-    {
+    for (size_t i = 0; i < count; ++i)
         delete [] (char *)hiov[i].iov_base;
-    }
 
     if (result < 0)
         return -errno;
@@ -695,14 +992,16 @@ writevFunc(SyscallDesc *desc, int callnum, Process *process,
 /// anything else.
 template <class OS>
 SyscallReturn
-mmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
+mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
 {
-    Addr start = xc->getSyscallArg(0);
-    uint64_t length = xc->getSyscallArg(1);
-    // int prot = xc->getSyscallArg(2);
-    int flags = xc->getSyscallArg(3);
-    // int fd = p->sim_fd(xc->getSyscallArg(4));
-    // int offset = xc->getSyscallArg(5);
+    int index = 0;
+    Addr start = p->getSyscallArg(tc, index);
+    uint64_t length = p->getSyscallArg(tc, index);
+    index++; // int prot = p->getSyscallArg(tc, index);
+    int flags = p->getSyscallArg(tc, index);
+    int fd = p->sim_fd(p->getSyscallArg(tc, index));
+    // int offset = p->getSyscallArg(tc, index);
+
 
     if ((start  % TheISA::VMPageSize) != 0 ||
         (length % TheISA::VMPageSize) != 0) {
@@ -718,13 +1017,18 @@ mmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
     }
 
     // pick next address from our "mmap region"
-    start = p->mmap_end;
+    if (OS::mmapGrowsDown()) {
+        start = p->mmap_end - length;
+        p->mmap_end = start;
+    } else {
+        start = p->mmap_end;
+        p->mmap_end += length;
+    }
     p->pTable->allocate(start, length);
-    p->mmap_end += length;
 
     if (!(flags & OS::TGT_MAP_ANONYMOUS)) {
         warn("allowing mmap of file @ fd %d. "
-             "This will break if not /dev/zero.", xc->getSyscallArg(4));
+             "This will break if not /dev/zero.", fd);
     }
 
     return start;
@@ -733,20 +1037,28 @@ mmapFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
 /// Target getrlimit() handler.
 template <class OS>
 SyscallReturn
-getrlimitFunc(SyscallDesc *desc, int callnum, Process *process,
-        ExecContext *xc)
+getrlimitFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+        ThreadContext *tc)
 {
-    unsigned resource = xc->getSyscallArg(0);
-    TypedBufferArg<typename OS::rlimit> rlp(xc->getSyscallArg(1));
+    int index = 0;
+    unsigned resource = process->getSyscallArg(tc, index);
+    TypedBufferArg<typename OS::rlimit> rlp(process->getSyscallArg(tc, index));
 
     switch (resource) {
         case OS::TGT_RLIMIT_STACK:
-            // max stack size in bytes: make up a number (2MB for now)
+            // max stack size in bytes: make up a number (8MB for now)
             rlp->rlim_cur = rlp->rlim_max = 8 * 1024 * 1024;
             rlp->rlim_cur = htog(rlp->rlim_cur);
             rlp->rlim_max = htog(rlp->rlim_max);
             break;
 
+        case OS::TGT_RLIMIT_DATA:
+            // max data segment size in bytes: make up a number
+            rlp->rlim_cur = rlp->rlim_max = 256 * 1024 * 1024;
+            rlp->rlim_cur = htog(rlp->rlim_cur);
+            rlp->rlim_max = htog(rlp->rlim_max);
+            break;
+
         default:
             std::cerr << "getrlimitFunc: unimplemented resource " << resource
                 << std::endl;
@@ -754,24 +1066,25 @@ getrlimitFunc(SyscallDesc *desc, int callnum, Process *process,
             break;
     }
 
-    rlp.copyOut(xc->getMemPort());
+    rlp.copyOut(tc->getMemPort());
     return 0;
 }
 
 /// Target gettimeofday() handler.
 template <class OS>
 SyscallReturn
-gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process,
-        ExecContext *xc)
+gettimeofdayFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+        ThreadContext *tc)
 {
-    TypedBufferArg<typename OS::timeval> tp(xc->getSyscallArg(0));
+    int index = 0;
+    TypedBufferArg<typename OS::timeval> tp(process->getSyscallArg(tc, index));
 
     getElapsedTime(tp->tv_sec, tp->tv_usec);
     tp->tv_sec += seconds_since_epoch;
-    tp->tv_sec = htog(tp->tv_sec);
-    tp->tv_usec = htog(tp->tv_usec);
+    tp->tv_sec = TheISA::htog(tp->tv_sec);
+    tp->tv_usec = TheISA::htog(tp->tv_usec);
 
-    tp.copyOut(xc->getMemPort());
+    tp.copyOut(tc->getMemPort());
 
     return 0;
 }
@@ -780,16 +1093,20 @@ gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process,
 /// Target utimes() handler.
 template <class OS>
 SyscallReturn
-utimesFunc(SyscallDesc *desc, int callnum, Process *process,
-           ExecContext *xc)
+utimesFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+           ThreadContext *tc)
 {
     std::string path;
 
-    if (!xc->getMemPort()->tryReadString(path, xc->getSyscallArg(0)))
-      return -EFAULT;
+    int index = 0;
+    if (!tc->getMemPort()->tryReadString(path,
+                process->getSyscallArg(tc, index))) {
+        return -EFAULT;
+    }
 
-    TypedBufferArg<typename OS::timeval [2]> tp(xc->getSyscallArg(1));
-    tp.copyIn(xc->getMemPort());
+    TypedBufferArg<typename OS::timeval [2]>
+        tp(process->getSyscallArg(tc, index));
+    tp.copyIn(tc->getMemPort());
 
     struct timeval hostTimeval[2];
     for (int i = 0; i < 2; ++i)
@@ -797,6 +1114,10 @@ utimesFunc(SyscallDesc *desc, int callnum, Process *process,
         hostTimeval[i].tv_sec = gtoh((*tp)[i].tv_sec);
         hostTimeval[i].tv_usec = gtoh((*tp)[i].tv_usec);
     }
+
+    // Adjust path for current working directory
+    path = process->fullPath(path);
+
     int result = utimes(path.c_str(), hostTimeval);
 
     if (result < 0)
@@ -807,23 +1128,15 @@ utimesFunc(SyscallDesc *desc, int callnum, Process *process,
 /// Target getrusage() function.
 template <class OS>
 SyscallReturn
-getrusageFunc(SyscallDesc *desc, int callnum, Process *process,
-              ExecContext *xc)
+getrusageFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+              ThreadContext *tc)
 {
-    int who = xc->getSyscallArg(0);    // THREAD, SELF, or CHILDREN
-    TypedBufferArg<typename OS::rusage> rup(xc->getSyscallArg(1));
-
-    if (who != OS::TGT_RUSAGE_SELF) {
-        // don't really handle THREAD or CHILDREN, but just warn and
-        // plow ahead
-        warn("getrusage() only supports RUSAGE_SELF.  Parameter %d ignored.",
-             who);
-    }
-
-    getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
-    rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec);
-    rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec);
+    int index = 0;
+    int who = process->getSyscallArg(tc, index); // THREAD, SELF, or CHILDREN
+    TypedBufferArg<typename OS::rusage> rup(process->getSyscallArg(tc, index));
 
+    rup->ru_utime.tv_sec = 0;
+    rup->ru_utime.tv_usec = 0;
     rup->ru_stime.tv_sec = 0;
     rup->ru_stime.tv_usec = 0;
     rup->ru_maxrss = 0;
@@ -841,12 +1154,75 @@ getrusageFunc(SyscallDesc *desc, int callnum, Process *process,
     rup->ru_nvcsw = 0;
     rup->ru_nivcsw = 0;
 
-    rup.copyOut(xc->getMemPort());
+    switch (who) {
+      case OS::TGT_RUSAGE_SELF:
+        getElapsedTime(rup->ru_utime.tv_sec, rup->ru_utime.tv_usec);
+        rup->ru_utime.tv_sec = htog(rup->ru_utime.tv_sec);
+        rup->ru_utime.tv_usec = htog(rup->ru_utime.tv_usec);
+        break;
+
+      case OS::TGT_RUSAGE_CHILDREN:
+        // do nothing.  We have no child processes, so they take no time.
+        break;
+
+      default:
+        // don't really handle THREAD or CHILDREN, but just warn and
+        // plow ahead
+        warn("getrusage() only supports RUSAGE_SELF.  Parameter %d ignored.",
+             who);
+    }
+
+    rup.copyOut(tc->getMemPort());
 
     return 0;
 }
 
+/// Target times() function.
+template <class OS>
+SyscallReturn
+timesFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+           ThreadContext *tc)
+{
+    int index = 0;
+    TypedBufferArg<typename OS::tms> bufp(process->getSyscallArg(tc, index));
+
+    // Fill in the time structure (in clocks)
+    int64_t clocks = curTick * OS::_SC_CLK_TCK / Clock::Int::s;
+    bufp->tms_utime = clocks;
+    bufp->tms_stime = 0;
+    bufp->tms_cutime = 0;
+    bufp->tms_cstime = 0;
+
+    // Convert to host endianness
+    bufp->tms_utime = htog(bufp->tms_utime);
 
+    // Write back
+    bufp.copyOut(tc->getMemPort());
+
+    // Return clock ticks since system boot
+    return clocks;
+}
+
+/// Target time() function.
+template <class OS>
+SyscallReturn
+timeFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+           ThreadContext *tc)
+{
+    typename OS::time_t sec, usec;
+    getElapsedTime(sec, usec);
+    sec += seconds_since_epoch;
+
+    int index = 0;
+    Addr taddr = (Addr)process->getSyscallArg(tc, index);
+    if(taddr != 0) {
+        typename OS::time_t t = sec;
+        t = htog(t);
+        TranslatingPort *p = tc->getMemPort();
+        p->writeBlob(taddr, (uint8_t*)&t, (int)sizeof(typename OS::time_t));
+    }
+    return sec;
+}
 
 
 #endif // __SIM_SYSCALL_EMUL_HH__