diff --git a/arch/alpha/alpha_linux_process.cc b/arch/alpha/alpha_linux_process.cc index 09039db90..83b0b5e5a 100644 --- a/arch/alpha/alpha_linux_process.cc +++ b/arch/alpha/alpha_linux_process.cc @@ -117,6 +117,29 @@ class Linux { uint32_t st_gen; //!< unknown }; + // same for stat64 + struct tgt_stat64 { + uint64_t st_dev; + uint64_t st_ino; + uint64_t st_rdev; + int64_t st_size; + uint64_t st_blocks; + + uint32_t st_mode; + uint32_t st_uid; + uint32_t st_gid; + uint32_t st_blksize; + uint32_t st_nlink; + uint32_t __pad0; + + uint64_t tgt_st_atime; + uint64_t st_atime_nsec; + uint64_t tgt_st_mtime; + uint64_t st_mtime_nsec; + uint64_t tgt_st_ctime; + uint64_t st_ctime_nsec; + int64_t __unused[3]; + }; /// Length of strings in struct utsname (plus 1 for null char). static const int _SYS_NMLN = 65; @@ -176,6 +199,12 @@ class Linux { int64_t tv_usec; //!< microseconds }; + // For writev/readv + struct tgt_iovec { + uint64_t iov_base; // void * + uint64_t iov_len; + }; + //@{ /// For getrusage(). static const int RUSAGE_SELF = 0; @@ -205,7 +234,7 @@ class Linux { /// Helper function to convert a host stat buffer to a target stat /// buffer. Also copies the target buffer out to the simulated - /// memorty space. Used by stat(), fstat(), and lstat(). + /// memory space. Used by stat(), fstat(), and lstat(). static void copyOutStatBuf(FunctionalMemory *mem, Addr addr, struct stat *host) { @@ -228,6 +257,40 @@ class Linux { tgt.copyOut(mem); } + // Same for stat64 + static void + copyOutStat64Buf(FunctionalMemory *mem, Addr addr, struct stat64 *host) + { + TypedBufferArg tgt(addr); + + // XXX byteswaps + tgt->st_dev = host->st_dev; + // XXX What about STAT64_HAS_BROKEN_ST_INO ??? + tgt->st_ino = host->st_ino; + tgt->st_rdev = host->st_rdev; + tgt->st_size = host->st_size; + tgt->st_blocks = host->st_blocks; + + tgt->st_mode = host->st_mode; + tgt->st_uid = host->st_uid; + tgt->st_gid = host->st_gid; + tgt->st_blksize = host->st_blksize; + tgt->st_nlink = host->st_nlink; + tgt->tgt_st_atime = host->st_atime; + tgt->tgt_st_mtime = host->st_mtime; + tgt->tgt_st_ctime = host->st_ctime; +#ifdef STAT_HAVE_NSEC + tgt->st_atime_nsec = host->st_atime_nsec; + tgt->st_mtime_nsec = host->st_mtime_nsec; + tgt->st_ctime_nsec = host->st_ctime_nsec; +#else + tgt->st_atime_nsec = 0; + tgt->st_mtime_nsec = 0; + tgt->st_ctime_nsec = 0; +#endif + tgt.copyOut(mem); + } + /// The target system's hostname. static const char *hostname; @@ -297,7 +360,7 @@ class Linux { } default: - cerr << "osf_getsysinfo: unknown op " << op << endl; + cerr << "osf_setsysinfo: unknown op " << op << endl; abort(); break; } @@ -429,8 +492,8 @@ SyscallDesc Linux::syscallDescs[] = { /* 12 */ SyscallDesc("chdir", unimplementedFunc), /* 13 */ SyscallDesc("fchdir", unimplementedFunc), /* 14 */ SyscallDesc("mknod", unimplementedFunc), - /* 15 */ SyscallDesc("chmod", unimplementedFunc), - /* 16 */ SyscallDesc("chown", unimplementedFunc), + /* 15 */ SyscallDesc("chmod", chmodFunc), + /* 16 */ SyscallDesc("chown", chownFunc), /* 17 */ SyscallDesc("brk", obreakFunc), /* 18 */ SyscallDesc("osf_getfsstat", unimplementedFunc), /* 19 */ SyscallDesc("lseek", lseekFunc), @@ -535,10 +598,10 @@ SyscallDesc Linux::syscallDescs[] = { /* 118 */ SyscallDesc("getsockopt", unimplementedFunc), /* 119 */ SyscallDesc("numa_syscalls", unimplementedFunc), /* 120 */ SyscallDesc("readv", unimplementedFunc), - /* 121 */ SyscallDesc("writev", unimplementedFunc), + /* 121 */ SyscallDesc("writev", writevFunc), /* 122 */ SyscallDesc("osf_settimeofday", unimplementedFunc), - /* 123 */ SyscallDesc("fchown", unimplementedFunc), - /* 124 */ SyscallDesc("fchmod", unimplementedFunc), + /* 123 */ SyscallDesc("fchown", fchownFunc), + /* 124 */ SyscallDesc("fchmod", fchmodFunc), /* 125 */ SyscallDesc("recvfrom", unimplementedFunc), /* 126 */ SyscallDesc("setreuid", unimplementedFunc), /* 127 */ SyscallDesc("setregid", unimplementedFunc), @@ -780,7 +843,7 @@ SyscallDesc Linux::syscallDescs[] = { /* 360 */ SyscallDesc("settimeofday", unimplementedFunc), /* 361 */ SyscallDesc("getitimer", unimplementedFunc), /* 362 */ SyscallDesc("setitimer", unimplementedFunc), - /* 363 */ SyscallDesc("utimes", unimplementedFunc), + /* 363 */ SyscallDesc("utimes", utimesFunc), /* 364 */ SyscallDesc("getrusage", getrusageFunc), /* 365 */ SyscallDesc("wait4", unimplementedFunc), /* 366 */ SyscallDesc("adjtimex", unimplementedFunc), @@ -841,7 +904,24 @@ SyscallDesc Linux::syscallDescs[] = { /* 421 */ SyscallDesc("clock_getres", unimplementedFunc), /* 422 */ SyscallDesc("clock_nanosleep", unimplementedFunc), /* 423 */ SyscallDesc("semtimedop", unimplementedFunc), - /* 424 */ SyscallDesc("tgkill", unimplementedFunc) + /* 424 */ SyscallDesc("tgkill", unimplementedFunc), + /* 425 */ SyscallDesc("stat64", unimplementedFunc), + /* 426 */ SyscallDesc("lstat64", lstat64Func), + /* 427 */ SyscallDesc("fstat64", fstat64Func), + /* 428 */ SyscallDesc("vserver", unimplementedFunc), + /* 429 */ SyscallDesc("mbind", unimplementedFunc), + /* 430 */ SyscallDesc("get_mempolicy", unimplementedFunc), + /* 431 */ SyscallDesc("set_mempolicy", unimplementedFunc), + /* 432 */ SyscallDesc("mq_open", unimplementedFunc), + /* 433 */ SyscallDesc("mq_unlink", unimplementedFunc), + /* 434 */ SyscallDesc("mq_timedsend", unimplementedFunc), + /* 435 */ SyscallDesc("mq_timedreceive", unimplementedFunc), + /* 436 */ SyscallDesc("mq_notify", unimplementedFunc), + /* 437 */ SyscallDesc("mq_getsetattr", unimplementedFunc), + /* 438 */ SyscallDesc("waitid", unimplementedFunc), + /* 439 */ SyscallDesc("add_key", unimplementedFunc), + /* 440 */ SyscallDesc("request_key", unimplementedFunc), + /* 441 */ SyscallDesc("keyctl", unimplementedFunc) }; const int Linux::Num_Syscall_Descs = diff --git a/sim/syscall_emul.cc b/sim/syscall_emul.cc index 50650018e..4b6388a41 100644 --- a/sim/syscall_emul.cc +++ b/sim/syscall_emul.cc @@ -242,3 +242,39 @@ ftruncateFunc(SyscallDesc *desc, int num, Process *process, ExecContext *xc) int result = ftruncate(fd, length); return (result == -1) ? -errno : result; } + +SyscallReturn +chownFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc) +{ + string path; + + if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) + return -EFAULT; + + /* XXX endianess */ + uint32_t owner = xc->getSyscallArg(1); + uid_t hostOwner = owner; + uint32_t group = xc->getSyscallArg(2); + gid_t hostGroup = group; + + int result = chown(path.c_str(), hostOwner, hostGroup); + return (result == -1) ? -errno : result; +} + +SyscallReturn +fchownFunc(SyscallDesc *desc, int num, Process *process, ExecContext *xc) +{ + int fd = process->sim_fd(xc->getSyscallArg(0)); + + if (fd < 0) + return -EBADF; + + /* XXX endianess */ + uint32_t owner = xc->getSyscallArg(1); + uid_t hostOwner = owner; + uint32_t group = xc->getSyscallArg(2); + gid_t hostGroup = group; + + int result = fchown(fd, hostOwner, hostGroup); + return (result == -1) ? -errno : result; +} diff --git a/sim/syscall_emul.hh b/sim/syscall_emul.hh index f22b6dcb7..2bd8969d7 100644 --- a/sim/syscall_emul.hh +++ b/sim/syscall_emul.hh @@ -40,6 +40,7 @@ #ifdef __CYGWIN32__ #include // for O_BINARY #endif +#include #include "base/intmath.hh" // for RoundUp #include "mem/functional/functional.hh" @@ -226,6 +227,15 @@ SyscallReturn ftruncateFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc); +/// Target chown() handler. +SyscallReturn chownFunc(SyscallDesc *desc, int num, + Process *p, ExecContext *xc); + + +/// Target fchown() handler. +SyscallReturn fchownFunc(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 { @@ -343,6 +353,59 @@ openFunc(SyscallDesc *desc, int callnum, Process *process, } +/// Target chmod() handler. +template +SyscallReturn +chmodFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + std::string path; + + if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) + return -EFAULT; + + uint32_t mode = xc->getSyscallArg(1); + mode_t hostMode = 0; + + // XXX translate mode flags via OS::something??? + hostMode = mode; + + // do the chmod + int result = chmod(path.c_str(), hostMode); + if (result < 0) + return errno; + + return 0; +} + + +/// Target fchmod() handler. +template +SyscallReturn +fchmodFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + int fd = xc->getSyscallArg(0); + 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); + mode_t hostMode = 0; + + // XXX translate mode flags via OS::someting??? + hostMode = mode; + + // do the fchmod + int result = fchmod(process->sim_fd(fd), hostMode); + if (result < 0) + return errno; + + return 0; +} + + /// Target stat() handler. template SyscallReturn @@ -366,6 +429,30 @@ statFunc(SyscallDesc *desc, int callnum, Process *process, } +/// Target fstat64() handler. +template +SyscallReturn +fstat64Func(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + int fd = xc->getSyscallArg(0); + if (fd < 0 || process->sim_fd(fd) < 0) { + // doesn't map to any simulator fd: not a valid target fd + return -EBADF; + } + + struct stat64 hostBuf; + int result = fstat64(process->sim_fd(fd), &hostBuf); + + if (result < 0) + return errno; + + OS::copyOutStat64Buf(xc->mem, xc->getSyscallArg(1), &hostBuf); + + return 0; +} + + /// Target lstat() handler. template SyscallReturn @@ -388,6 +475,28 @@ lstatFunc(SyscallDesc *desc, int callnum, Process *process, return 0; } +/// Target lstat64() handler. +template +SyscallReturn +lstat64Func(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + std::string path; + + if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) + return -EFAULT; + + struct stat64 hostBuf; + int result = lstat64(path.c_str(), &hostBuf); + + if (result < 0) + return -errno; + + OS::copyOutStat64Buf(xc->mem, xc->getSyscallArg(1), &hostBuf); + + return 0; +} + /// Target fstat() handler. template SyscallReturn @@ -459,6 +568,46 @@ fstatfsFunc(SyscallDesc *desc, int callnum, Process *process, } +/// Target writev() handler. +template +SyscallReturn +writevFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + int fd = xc->getSyscallArg(0); + if (fd < 0 || process->sim_fd(fd) < 0) { + // doesn't map to any simulator fd: not a valid target fd + return -EBADF; + } + + uint64_t tiov_base = xc->getSyscallArg(1); + size_t count = xc->getSyscallArg(2); + struct iovec hiov[count]; + for (int i = 0; i < count; ++i) + { + typename OS::tgt_iovec tiov; + xc->mem->access(Read, tiov_base + i*sizeof(typename OS::tgt_iovec), + &tiov, sizeof(typename OS::tgt_iovec)); + hiov[i].iov_len = tiov.iov_len; + hiov[i].iov_base = new char [hiov[i].iov_len]; + xc->mem->access(Read, tiov.iov_base, + hiov[i].iov_base, hiov[i].iov_len); + } + + int result = writev(process->sim_fd(fd), hiov, count); + + for (int i = 0; i < count; ++i) + { + delete [] (char *)hiov[i].iov_base; + } + + if (result < 0) + return errno; + + return 0; +} + + /// Target mmap() handler. /// /// We don't really handle mmap(). If the target is mmaping an @@ -543,6 +692,34 @@ gettimeofdayFunc(SyscallDesc *desc, int callnum, Process *process, } +/// Target utimes() handler. +template +SyscallReturn +utimesFunc(SyscallDesc *desc, int callnum, Process *process, + ExecContext *xc) +{ + std::string path; + + if (xc->mem->readString(path, xc->getSyscallArg(0)) != No_Fault) + return -EFAULT; + + TypedBufferArg tp(xc->getSyscallArg(1)); + tp.copyIn(xc->mem); + + struct timeval hostTimeval[2]; + for (int i = 0; i < 2; ++i) + { + hostTimeval[i].tv_sec = (*tp)[i].tv_sec; + hostTimeval[i].tv_usec = (*tp)[i].tv_usec; + } + int result = utimes(path.c_str(), hostTimeval); + + if (result < 0) + return -errno; + + return 0; +} + /// Target getrusage() function. template SyscallReturn