From 37495f8823cfb2d871e6c3c4012e1e81d69a8b94 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Tue, 12 Oct 2021 17:00:16 +0100 Subject: [PATCH] misc: Using OS::size_t in syscall signature Using the host size_t is confusing the guest ABI engine every time the host and the guest adopt a different data model (ILP32 vs LP64) For example when a LP64 machine is running an ILP32 application in SE mode, "size_t" will wrongly inform the guest ABI engine to retrieve the argument by loading a 64 bit (instead of 32) value from the stack JIRA: https://gem5.atlassian.net/browse/GEM5-1074 Change-Id: Id7d7740ac429f534a4089331bedf21dc3951bbad Signed-off-by: Giacomo Travaglini Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/51489 Reviewed-by: Jason Lowe-Power Reviewed-by: Gabe Black Maintainer: Jason Lowe-Power Tested-by: kokoro --- src/arch/arm/freebsd/se_workload.cc | 2 +- src/arch/arm/linux/se_workload.cc | 16 +- src/arch/mips/linux/se_workload.cc | 4 +- src/arch/power/linux/se_workload.cc | 4 +- src/arch/riscv/linux/se_workload.cc | 8 +- src/arch/sparc/linux/syscalls.cc | 8 +- src/arch/x86/linux/syscall_tbl32.cc | 6 +- src/arch/x86/linux/syscall_tbl64.cc | 10 +- src/sim/syscall_emul.cc | 178 ---------------------- src/sim/syscall_emul.hh | 220 ++++++++++++++++++++++++---- 10 files changed, 220 insertions(+), 236 deletions(-) diff --git a/src/arch/arm/freebsd/se_workload.cc b/src/arch/arm/freebsd/se_workload.cc index 542510b9ac..66e587e54c 100644 --- a/src/arch/arm/freebsd/se_workload.cc +++ b/src/arch/arm/freebsd/se_workload.cc @@ -136,7 +136,7 @@ static SyscallDescTable syscallDescs64 = { { 4, "write", writeFunc }, { 17, "obreak", brkFunc }, { 54, "ioctl", ioctlFunc }, - { 58, "readlink", readlinkFunc }, + { 58, "readlink", readlinkFunc }, { 117, "getrusage", getrusageFunc }, { 189, "fstat", fstatFunc }, #if !defined ( __GNU_LIBRARY__ ) diff --git a/src/arch/arm/linux/se_workload.cc b/src/arch/arm/linux/se_workload.cc index 450d5405a6..c715e1db14 100644 --- a/src/arch/arm/linux/se_workload.cc +++ b/src/arch/arm/linux/se_workload.cc @@ -216,13 +216,13 @@ class SyscallTable32 : public SyscallDescTable { base + 81, "setgroups" }, { base + 82, "reserved#82" }, { base + 83, "symlink" }, - { base + 85, "readlink", readlinkFunc }, + { base + 85, "readlink", readlinkFunc }, { base + 86, "uselib" }, { base + 87, "swapon" }, { base + 88, "reboot" }, { base + 89, "readdir" }, { base + 90, "mmap", mmapFunc }, - { base + 91, "munmap", munmapFunc }, + { base + 91, "munmap", munmapFunc }, { base + 92, "truncate", truncateFunc }, { base + 93, "ftruncate", ftruncateFunc }, { base + 94, "fchmod" }, @@ -413,9 +413,9 @@ class SyscallTable32 : public SyscallDescTable { base + 287, "getpeername" }, { base + 288, "socketpair" }, { base + 289, "send" }, - { base + 290, "sendto", sendtoFunc }, + { base + 290, "sendto", sendtoFunc }, { base + 291, "recv" }, - { base + 292, "recvfrom", recvfromFunc }, + { base + 292, "recvfrom", recvfromFunc }, { base + 293, "shutdown" }, { base + 294, "setsockopt" }, { base + 295, "getsockopt" }, @@ -708,8 +708,8 @@ class SyscallTable64 : public SyscallDescTable { base + 203, "connect" }, { base + 204, "getsockname" }, { base + 205, "getpeername" }, - { base + 206, "sendto", sendtoFunc }, - { base + 207, "recvfrom", recvfromFunc }, + { base + 206, "sendto", sendtoFunc }, + { base + 207, "recvfrom", recvfromFunc }, { base + 208, "setsockopt" }, { base + 209, "getsockopt" }, { base + 210, "shutdown" }, @@ -717,7 +717,7 @@ class SyscallTable64 : public SyscallDescTable { base + 212, "recvmsg" }, { base + 213, "readahead" }, { base + 214, "brk", brkFunc }, - { base + 215, "munmap", munmapFunc }, + { base + 215, "munmap", munmapFunc }, { base + 216, "mremap", mremapFunc }, { base + 217, "add_key" }, { base + 218, "request_key" }, @@ -769,7 +769,7 @@ class SyscallTable64 : public SyscallDescTable { base + 1032, "lchown" }, { base + 1033, "access", accessFunc }, { base + 1034, "rename", renameFunc }, - { base + 1035, "readlink", readlinkFunc }, + { base + 1035, "readlink", readlinkFunc }, { base + 1036, "symlink" }, { base + 1037, "utimes" }, { base + 1038, "stat64", stat64Func }, diff --git a/src/arch/mips/linux/se_workload.cc b/src/arch/mips/linux/se_workload.cc index 647c0cac3e..09752d1525 100644 --- a/src/arch/mips/linux/se_workload.cc +++ b/src/arch/mips/linux/se_workload.cc @@ -243,13 +243,13 @@ SyscallDescTable EmuLinux::syscallDescs = { { 4082, "reserved#82" }, { 4083, "symlink" }, { 4084, "unused#84" }, - { 4085, "readlink", readlinkFunc }, + { 4085, "readlink", readlinkFunc }, { 4086, "uselib" }, { 4087, "swapon", gethostnameFunc }, { 4088, "reboot" }, { 4089, "readdir" }, { 4090, "mmap", mmapFunc }, - { 4091, "munmap",munmapFunc }, + { 4091, "munmap",munmapFunc }, { 4092, "truncate", truncateFunc }, { 4093, "ftruncate", ftruncateFunc }, { 4094, "fchmod", fchmodFunc }, diff --git a/src/arch/power/linux/se_workload.cc b/src/arch/power/linux/se_workload.cc index b49cb0b11b..975d5ddcca 100644 --- a/src/arch/power/linux/se_workload.cc +++ b/src/arch/power/linux/se_workload.cc @@ -192,13 +192,13 @@ SyscallDescTable EmuLinux::syscallDescs = { { 82, "reserved#82" }, { 83, "symlink" }, { 84, "unused#84" }, - { 85, "readlink", readlinkFunc }, + { 85, "readlink", readlinkFunc }, { 86, "uselib" }, { 87, "swapon", gethostnameFunc }, { 88, "reboot" }, { 89, "readdir" }, { 90, "mmap", mmapFunc }, - { 91, "munmap",munmapFunc }, + { 91, "munmap",munmapFunc }, { 92, "truncate", truncateFunc }, { 93, "ftruncate", ftruncateFunc }, { 94, "fchmod" }, diff --git a/src/arch/riscv/linux/se_workload.cc b/src/arch/riscv/linux/se_workload.cc index 18627a79b1..3b0079dc1e 100644 --- a/src/arch/riscv/linux/se_workload.cc +++ b/src/arch/riscv/linux/se_workload.cc @@ -338,7 +338,7 @@ SyscallDescTable EmuLinux::syscallDescs64 = { { 212, "recvmsg" }, { 213, "readahead" }, { 214, "brk", brkFunc }, - { 215, "munmap", munmapFunc }, + { 215, "munmap", munmapFunc }, { 216, "mremap", mremapFunc }, { 217, "add_key" }, { 218, "request_key" }, @@ -406,7 +406,7 @@ SyscallDescTable EmuLinux::syscallDescs64 = { { 1032, "lchown" }, { 1033, "access", accessFunc }, { 1034, "rename", renameFunc }, - { 1035, "readlink", readlinkFunc }, + { 1035, "readlink", readlinkFunc }, { 1036, "symlink" }, { 1037, "utimes", utimesFunc }, { 1038, "stat", stat64Func }, @@ -669,7 +669,7 @@ SyscallDescTable EmuLinux::syscallDescs32 = { { 212, "recvmsg" }, { 213, "readahead" }, { 214, "brk", brkFunc }, - { 215, "munmap", munmapFunc }, + { 215, "munmap", munmapFunc }, { 216, "mremap", mremapFunc }, { 217, "add_key" }, { 218, "request_key" }, @@ -737,7 +737,7 @@ SyscallDescTable EmuLinux::syscallDescs32 = { { 1032, "lchown" }, { 1033, "access", accessFunc }, { 1034, "rename", renameFunc }, - { 1035, "readlink", readlinkFunc }, + { 1035, "readlink", readlinkFunc }, { 1036, "symlink" }, { 1037, "utimes", utimesFunc }, { 1038, "stat", statFunc }, diff --git a/src/arch/sparc/linux/syscalls.cc b/src/arch/sparc/linux/syscalls.cc index ae89b37b03..093fc9ccd3 100644 --- a/src/arch/sparc/linux/syscalls.cc +++ b/src/arch/sparc/linux/syscalls.cc @@ -143,7 +143,7 @@ SyscallDescTable EmuLinux::syscall32Descs = { { 55, "reboot" }, // 32 bit { 56, "mmap2" }, // 32 bit { 57, "symlink" }, - { 58, "readlink", readlinkFunc }, // 32 bit + { 58, "readlink", readlinkFunc }, // 32 bit { 59, "execve" }, // 32 bit { 60, "umask" }, // 32 bit { 61, "chroot" }, @@ -158,7 +158,7 @@ SyscallDescTable EmuLinux::syscall32Descs = { { 70, "getegid32" }, { 71, "mmap", mmapFunc }, { 72, "setreuid32" }, - { 73, "munmap", munmapFunc }, + { 73, "munmap", munmapFunc }, { 74, "mprotect", ignoreFunc }, { 75, "madvise" }, { 76, "vhangup" }, @@ -446,7 +446,7 @@ SyscallDescTable EmuLinux::syscallDescs = { { 55, "reboot" }, { 56, "mmap2" }, { 57, "symlink" }, - { 58, "readlink", readlinkFunc }, + { 58, "readlink", readlinkFunc }, { 59, "execve" }, { 60, "umask" }, { 61, "chroot" }, @@ -461,7 +461,7 @@ SyscallDescTable EmuLinux::syscallDescs = { { 70, "getegid32" }, { 71, "mmap", mmapFunc }, { 72, "setreuid32" }, - { 73, "munmap", munmapFunc }, + { 73, "munmap", munmapFunc }, { 74, "mprotect", ignoreFunc }, { 75, "madvise" }, { 76, "vhangup" }, diff --git a/src/arch/x86/linux/syscall_tbl32.cc b/src/arch/x86/linux/syscall_tbl32.cc index 112719c64d..43b2a7166c 100644 --- a/src/arch/x86/linux/syscall_tbl32.cc +++ b/src/arch/x86/linux/syscall_tbl32.cc @@ -124,13 +124,13 @@ SyscallDescTable EmuLinux::syscallDescs32 = { { 82, "select", selectFunc }, { 83, "symlink" }, { 84, "oldlstat" }, - { 85, "readlink", readlinkFunc }, + { 85, "readlink", readlinkFunc }, { 86, "uselib" }, { 87, "swapon" }, { 88, "reboot" }, { 89, "readdir" }, { 90, "mmap" }, - { 91, "munmap", munmapFunc }, + { 91, "munmap", munmapFunc }, { 92, "truncate", truncateFunc }, { 93, "ftruncate", ftruncateFunc }, { 94, "fchmod" }, @@ -352,7 +352,7 @@ SyscallDescTable EmuLinux::syscallDescs32 = { { 302, "renameat" }, { 303, "linkat" }, { 304, "symlinkat" }, - { 305, "readlinkat", readlinkFunc }, + { 305, "readlinkat", readlinkFunc }, { 306, "fchmodat" }, { 307, "faccessat" }, { 308, "pselect6" }, diff --git a/src/arch/x86/linux/syscall_tbl64.cc b/src/arch/x86/linux/syscall_tbl64.cc index 5c983c03b9..b6c5103059 100644 --- a/src/arch/x86/linux/syscall_tbl64.cc +++ b/src/arch/x86/linux/syscall_tbl64.cc @@ -50,7 +50,7 @@ SyscallDescTable EmuLinux::syscallDescs64 = { { 8, "lseek", lseekFunc }, { 9, "mmap", mmapFunc }, { 10, "mprotect", ignoreFunc }, - { 11, "munmap", munmapFunc }, + { 11, "munmap", munmapFunc }, { 12, "brk", brkFunc }, { 13, "rt_sigaction", ignoreWarnOnceFunc }, { 14, "rt_sigprocmask", ignoreWarnOnceFunc }, @@ -83,8 +83,8 @@ SyscallDescTable EmuLinux::syscallDescs64 = { { 41, "socket", socketFunc }, { 42, "connect", connectFunc }, { 43, "accept", acceptFunc }, - { 44, "sendto", sendtoFunc }, - { 45, "recvfrom", recvfromFunc }, + { 44, "sendto", sendtoFunc }, + { 45, "recvfrom", recvfromFunc }, { 46, "sendmsg", sendmsgFunc }, { 47, "recvmsg", recvmsgFunc }, { 48, "shutdown", shutdownFunc }, @@ -132,7 +132,7 @@ SyscallDescTable EmuLinux::syscallDescs64 = { { 86, "link", linkFunc }, { 87, "unlink", unlinkFunc }, { 88, "symlink", symlinkFunc }, - { 89, "readlink", readlinkFunc }, + { 89, "readlink", readlinkFunc }, { 90, "chmod", ignoreFunc }, { 91, "fchmod" }, { 92, "chown" }, @@ -314,7 +314,7 @@ SyscallDescTable EmuLinux::syscallDescs64 = { { 264, "renameat" }, { 265, "linkat" }, { 266, "symlinkat" }, - { 267, "readlinkat", readlinkFunc }, + { 267, "readlinkat", readlinkFunc }, { 268, "fchmodat" }, { 269, "faccessat" }, { 270, "pselect6" }, diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index 3a732c0c08..45f14be3c7 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -336,26 +336,6 @@ _llseekFunc(SyscallDesc *desc, ThreadContext *tc, } -SyscallReturn -munmapFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> start, size_t length) -{ - // Even if the system is currently not capable of recycling physical - // pages, there is no reason we can't unmap them so that we trigger - // appropriate seg faults when the application mistakenly tries to - // access them again. - auto p = tc->getProcessPtr(); - - if (p->pTable->pageOffset(start)) - return -EINVAL; - - length = roundUp(length, p->pTable->pageSize()); - - p->memState->unmapRegion(start, length); - - return 0; -} - - const char *hostname = "m5.eecs.umich.edu"; SyscallReturn @@ -398,71 +378,6 @@ getcwdFunc(SyscallDesc *desc, ThreadContext *tc, return (result == -1) ? -errno : result; } -SyscallReturn -readlinkFunc(SyscallDesc *desc, ThreadContext *tc, - VPtr<> pathname, VPtr<> buf_ptr, size_t bufsiz) -{ - std::string path; - if (!SETranslatingPortProxy(tc).tryReadString(path, pathname)) - return -EFAULT; - - return readlinkImpl(desc, tc, path, buf_ptr, bufsiz); -} - -SyscallReturn -readlinkImpl(SyscallDesc *desc, ThreadContext *tc, - std::string path, VPtr<> buf_ptr, size_t bufsiz) -{ - auto p = tc->getProcessPtr(); - - // Adjust path for cwd and redirection - path = p->checkPathRedirect(path); - - BufferArg buf(buf_ptr, bufsiz); - - int result = -1; - if (path != "/proc/self/exe") { - result = readlink(path.c_str(), (char *)buf.bufferPtr(), bufsiz); - } else { - // Emulate readlink() called on '/proc/self/exe' should return the - // absolute path of the binary running in the simulated system (the - // Process' executable). It is possible that using this path in - // the simulated system will result in unexpected behavior if: - // 1) One binary runs another (e.g., -c time -o "my_binary"), and - // called binary calls readlink(). - // 2) The host's full path to the running benchmark changes from one - // simulation to another. This can result in different simulated - // performance since the simulated system will process the binary - // path differently, even if the binary itself does not change. - - // Get the absolute canonical path to the running application - char real_path[PATH_MAX]; - char *check_real_path = realpath(p->progName(), real_path); - if (!check_real_path) { - fatal("readlink('/proc/self/exe') unable to resolve path to " - "executable: %s", p->progName()); - } - strncpy((char*)buf.bufferPtr(), real_path, bufsiz); - size_t real_path_len = strlen(real_path); - if (real_path_len > bufsiz) { - // readlink will truncate the contents of the - // path to ensure it is no more than bufsiz - result = bufsiz; - } else { - result = real_path_len; - } - - // Issue a warning about potential unexpected results - warn_once("readlink() called on '/proc/self/exe' may yield unexpected " - "results in various settings.\n Returning '%s'\n", - (char*)buf.bufferPtr()); - } - - buf.copyOut(SETranslatingPortProxy(tc)); - - return (result == -1) ? -errno : result; -} - SyscallReturn unlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname) { @@ -1263,99 +1178,6 @@ connectFunc(SyscallDesc *desc, ThreadContext *tc, return (status == -1) ? -errno : status; } -SyscallReturn -recvfromFunc(SyscallDesc *desc, ThreadContext *tc, - int tgt_fd, VPtr<> bufrPtr, size_t bufrLen, int flags, - VPtr<> addrPtr, VPtr<> addrlenPtr) -{ - auto p = tc->getProcessPtr(); - - auto sfdp = std::dynamic_pointer_cast((*p->fds)[tgt_fd]); - if (!sfdp) - return -EBADF; - int sim_fd = sfdp->getSimFD(); - - // Reserve buffer space. - BufferArg bufrBuf(bufrPtr, bufrLen); - - SETranslatingPortProxy proxy(tc); - - // Get address length. - socklen_t addrLen = 0; - if (addrlenPtr != 0) { - // Read address length parameter. - BufferArg addrlenBuf(addrlenPtr, sizeof(socklen_t)); - addrlenBuf.copyIn(proxy); - addrLen = *((socklen_t *)addrlenBuf.bufferPtr()); - } - - struct sockaddr sa, *sap = NULL; - if (addrLen != 0) { - BufferArg addrBuf(addrPtr, addrLen); - addrBuf.copyIn(proxy); - memcpy(&sa, (struct sockaddr *)addrBuf.bufferPtr(), - sizeof(struct sockaddr)); - sap = &sa; - } - - ssize_t recvd_size = recvfrom(sim_fd, - (void *)bufrBuf.bufferPtr(), - bufrLen, flags, sap, (socklen_t *)&addrLen); - - if (recvd_size == -1) - return -errno; - - // Pass the received data out. - bufrBuf.copyOut(proxy); - - // Copy address to addrPtr and pass it on. - if (sap != NULL) { - BufferArg addrBuf(addrPtr, addrLen); - memcpy(addrBuf.bufferPtr(), sap, sizeof(sa)); - addrBuf.copyOut(proxy); - } - - // Copy len to addrlenPtr and pass it on. - if (addrLen != 0) { - BufferArg addrlenBuf(addrlenPtr, sizeof(socklen_t)); - *(socklen_t *)addrlenBuf.bufferPtr() = addrLen; - addrlenBuf.copyOut(proxy); - } - - return recvd_size; -} - -SyscallReturn -sendtoFunc(SyscallDesc *desc, ThreadContext *tc, - int tgt_fd, VPtr<> bufrPtr, size_t bufrLen, int flags, - VPtr<> addrPtr, socklen_t addrLen) -{ - auto p = tc->getProcessPtr(); - - auto sfdp = std::dynamic_pointer_cast((*p->fds)[tgt_fd]); - if (!sfdp) - return -EBADF; - int sim_fd = sfdp->getSimFD(); - - // Reserve buffer space. - BufferArg bufrBuf(bufrPtr, bufrLen); - bufrBuf.copyIn(SETranslatingPortProxy(tc)); - - struct sockaddr sa, *sap = nullptr; - memset(&sa, 0, sizeof(sockaddr)); - if (addrLen != 0) { - BufferArg addrBuf(addrPtr, addrLen); - addrBuf.copyIn(SETranslatingPortProxy(tc)); - memcpy(&sa, (sockaddr*)addrBuf.bufferPtr(), addrLen); - sap = &sa; - } - - ssize_t sent_size = sendto(sim_fd, - (void *)bufrBuf.bufferPtr(), - bufrLen, flags, sap, (socklen_t)addrLen); - - return (sent_size == -1) ? -errno : sent_size; -} SyscallReturn recvmsgFunc(SyscallDesc *desc, ThreadContext *tc, diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index e46f059fd3..0923e633bf 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -172,10 +172,6 @@ SyscallReturn _llseekFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, uint64_t offset_high, uint32_t offset_low, VPtr<> result_ptr, int whence); -/// Target munmap() handler. -SyscallReturn munmapFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> start, - size_t length); - /// Target shutdown() handler. SyscallReturn shutdownFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, int how); @@ -188,12 +184,6 @@ SyscallReturn gethostnameFunc(SyscallDesc *desc, ThreadContext *tc, SyscallReturn getcwdFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> buf_ptr, unsigned long size); -/// Target readlink() handler. -SyscallReturn readlinkFunc(SyscallDesc *desc, ThreadContext *tc, - VPtr<> pathname, VPtr<> buf, size_t bufsiz); -SyscallReturn readlinkImpl(SyscallDesc *desc, ThreadContext *tc, - std::string path, VPtr<> buf, size_t bufsiz); - /// Target unlink() handler. SyscallReturn unlinkFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> pathname); @@ -325,16 +315,6 @@ SyscallReturn getdents64Func(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> buf_ptr, unsigned count); #endif -// Target sendto() handler. -SyscallReturn sendtoFunc(SyscallDesc *desc, ThreadContext *tc, - int tgt_fd, VPtr<> bufrPtr, size_t bufrLen, int flags, - VPtr<> addrPtr, socklen_t addrLen); - -// Target recvfrom() handler. -SyscallReturn recvfromFunc(SyscallDesc *desc, ThreadContext *tc, - int tgt_fd, VPtr<> bufrPtr, size_t bufrLen, - int flags, VPtr<> addrPtr, VPtr<> addrlenPtr); - // Target recvmsg() handler. SyscallReturn recvmsgFunc(SyscallDesc *desc, ThreadContext *tc, int tgt_fd, VPtr<> msgPtr, int flags); @@ -979,7 +959,8 @@ faccessatFunc(SyscallDesc *desc, ThreadContext *tc, template SyscallReturn readlinkatFunc(SyscallDesc *desc, ThreadContext *tc, - int dirfd, VPtr<> pathname, VPtr<> buf, size_t bufsiz) + int dirfd, VPtr<> pathname, VPtr<> buf_ptr, + typename OS::size_t bufsiz) { std::string path; if (!SETranslatingPortProxy(tc).tryReadString(path, pathname)) @@ -990,7 +971,65 @@ readlinkatFunc(SyscallDesc *desc, ThreadContext *tc, return res; } - return readlinkImpl(desc, tc, path, buf, bufsiz); + auto p = tc->getProcessPtr(); + + // Adjust path for cwd and redirection + path = p->checkPathRedirect(path); + + BufferArg buf(buf_ptr, bufsiz); + + int result = -1; + if (path != "/proc/self/exe") { + result = readlink(path.c_str(), (char *)buf.bufferPtr(), bufsiz); + } else { + // Emulate readlink() called on '/proc/self/exe' should return the + // absolute path of the binary running in the simulated system (the + // Process' executable). It is possible that using this path in + // the simulated system will result in unexpected behavior if: + // 1) One binary runs another (e.g., -c time -o "my_binary"), and + // called binary calls readlink(). + // 2) The host's full path to the running benchmark changes from one + // simulation to another. This can result in different simulated + // performance since the simulated system will process the binary + // path differently, even if the binary itself does not change. + + // Get the absolute canonical path to the running application + char real_path[PATH_MAX]; + char *check_real_path = realpath(p->progName(), real_path); + if (!check_real_path) { + fatal("readlink('/proc/self/exe') unable to resolve path to " + "executable: %s", p->progName()); + } + strncpy((char*)buf.bufferPtr(), real_path, bufsiz); + typename OS::size_t real_path_len = strlen(real_path); + if (real_path_len > bufsiz) { + // readlink will truncate the contents of the + // path to ensure it is no more than bufsiz + result = bufsiz; + } else { + result = real_path_len; + } + + // Issue a warning about potential unexpected results + warn_once("readlink() called on '/proc/self/exe' may yield unexpected " + "results in various settings.\n Returning '%s'\n", + (char*)buf.bufferPtr()); + } + + buf.copyOut(SETranslatingPortProxy(tc)); + + return (result == -1) ? -errno : result; +} + +/// Target readlink() handler +template +SyscallReturn +readlinkFunc(SyscallDesc *desc, ThreadContext *tc, + VPtr<> pathname, VPtr<> buf_ptr, + typename OS::size_t bufsiz) +{ + return readlinkatFunc(desc, tc, OS::TGT_AT_FDCWD, + pathname, buf_ptr, bufsiz); } /// Target renameat() handler. @@ -1625,7 +1664,8 @@ fstatfsFunc(SyscallDesc *desc, ThreadContext *tc, template SyscallReturn readvFunc(SyscallDesc *desc, ThreadContext *tc, - int tgt_fd, uint64_t tiov_base, size_t count) + int tgt_fd, uint64_t tiov_base, + typename OS::size_t count) { auto p = tc->getProcessPtr(); @@ -1637,7 +1677,7 @@ readvFunc(SyscallDesc *desc, ThreadContext *tc, SETranslatingPortProxy prox(tc); typename OS::tgt_iovec tiov[count]; struct iovec hiov[count]; - for (size_t i = 0; i < count; ++i) { + for (typename OS::size_t i = 0; i < count; ++i) { prox.readBlob(tiov_base + (i * sizeof(typename OS::tgt_iovec)), &tiov[i], sizeof(typename OS::tgt_iovec)); hiov[i].iov_len = gtoh(tiov[i].iov_len, OS::byteOrder); @@ -1647,7 +1687,7 @@ readvFunc(SyscallDesc *desc, ThreadContext *tc, int result = readv(sim_fd, hiov, count); int local_errno = errno; - for (size_t i = 0; i < count; ++i) { + for (typename OS::size_t i = 0; i < count; ++i) { if (result != -1) { prox.writeBlob(htog(tiov[i].iov_base, OS::byteOrder), hiov[i].iov_base, hiov[i].iov_len); @@ -1662,7 +1702,8 @@ readvFunc(SyscallDesc *desc, ThreadContext *tc, template SyscallReturn writevFunc(SyscallDesc *desc, ThreadContext *tc, - int tgt_fd, uint64_t tiov_base, size_t count) + int tgt_fd, uint64_t tiov_base, + typename OS::size_t count) { auto p = tc->getProcessPtr(); @@ -1673,7 +1714,7 @@ writevFunc(SyscallDesc *desc, ThreadContext *tc, SETranslatingPortProxy prox(tc); struct iovec hiov[count]; - for (size_t i = 0; i < count; ++i) { + for (typename OS::size_t i = 0; i < count; ++i) { typename OS::tgt_iovec tiov; prox.readBlob(tiov_base + i*sizeof(typename OS::tgt_iovec), @@ -1686,7 +1727,7 @@ writevFunc(SyscallDesc *desc, ThreadContext *tc, int result = writev(sim_fd, hiov, count); - for (size_t i = 0; i < count; ++i) + for (typename OS::size_t i = 0; i < count; ++i) delete [] (char *)hiov[i].iov_base; return (result == -1) ? -errno : result; @@ -2695,7 +2736,8 @@ eventfdFunc(SyscallDesc *desc, ThreadContext *tc, template SyscallReturn schedGetaffinityFunc(SyscallDesc *desc, ThreadContext *tc, - pid_t pid, size_t cpusetsize, VPtr<> cpu_set_mask) + pid_t pid, typename OS::size_t cpusetsize, + VPtr<> cpu_set_mask) { #if defined(__linux__) if (cpusetsize < CPU_ALLOC_SIZE(tc->getSystemPtr()->threads.size())) @@ -2715,6 +2757,126 @@ schedGetaffinityFunc(SyscallDesc *desc, ThreadContext *tc, #endif } +// Target recvfrom() handler. +template +SyscallReturn +recvfromFunc(SyscallDesc *desc, ThreadContext *tc, + int tgt_fd, VPtr<> buf_ptr, typename OS::size_t buf_len, + int flags, VPtr<> addr_ptr, VPtr<> addrlen_ptr) +{ + auto p = tc->getProcessPtr(); + + auto sfdp = std::dynamic_pointer_cast((*p->fds)[tgt_fd]); + if (!sfdp) + return -EBADF; + int sim_fd = sfdp->getSimFD(); + + // Reserve buffer space. + BufferArg buf(buf_ptr, buf_len); + + SETranslatingPortProxy proxy(tc); + + // Get address length. + socklen_t addr_len = 0; + if (addrlen_ptr != 0) { + // Read address length parameter. + BufferArg addrlen_buf(addrlen_ptr, sizeof(socklen_t)); + addrlen_buf.copyIn(proxy); + addr_len = *((socklen_t *)addrlen_buf.bufferPtr()); + } + + struct sockaddr sa, *sap = NULL; + if (addr_len != 0) { + BufferArg addr_buf(addr_ptr, addr_len); + addr_buf.copyIn(proxy); + memcpy(&sa, (struct sockaddr *)addr_buf.bufferPtr(), + sizeof(struct sockaddr)); + sap = &sa; + } + + ssize_t recvd_size = recvfrom(sim_fd, + (void *)buf.bufferPtr(), + buf_len, flags, sap, (socklen_t *)&addr_len); + + if (recvd_size == -1) + return -errno; + + // Pass the received data out. + buf.copyOut(proxy); + + // Copy address to addr_ptr and pass it on. + if (sap != NULL) { + BufferArg addr_buf(addr_ptr, addr_len); + memcpy(addr_buf.bufferPtr(), sap, sizeof(sa)); + addr_buf.copyOut(proxy); + } + + // Copy len to addrlen_ptr and pass it on. + if (addr_len != 0) { + BufferArg addrlen_buf(addrlen_ptr, sizeof(socklen_t)); + *(socklen_t *)addrlen_buf.bufferPtr() = addr_len; + addrlen_buf.copyOut(proxy); + } + + return recvd_size; +} + +// Target sendto() handler. +template +SyscallReturn +sendtoFunc(SyscallDesc *desc, ThreadContext *tc, + int tgt_fd, VPtr<> buf_ptr, typename OS::size_t buf_len, int flags, + VPtr<> addr_ptr, socklen_t addr_len) +{ + auto p = tc->getProcessPtr(); + + auto sfdp = std::dynamic_pointer_cast((*p->fds)[tgt_fd]); + if (!sfdp) + return -EBADF; + int sim_fd = sfdp->getSimFD(); + + // Reserve buffer space. + BufferArg buf(buf_ptr, buf_len); + buf.copyIn(SETranslatingPortProxy(tc)); + + struct sockaddr sa, *sap = nullptr; + memset(&sa, 0, sizeof(sockaddr)); + if (addr_len != 0) { + BufferArg addr_buf(addr_ptr, addr_len); + addr_buf.copyIn(SETranslatingPortProxy(tc)); + memcpy(&sa, (sockaddr*)addr_buf.bufferPtr(), addr_len); + sap = &sa; + } + + ssize_t sent_size = sendto(sim_fd, + (void *)buf.bufferPtr(), + buf_len, flags, sap, (socklen_t)addr_len); + + return (sent_size == -1) ? -errno : sent_size; +} + +/// Target munmap() handler. +template +SyscallReturn +munmapFunc(SyscallDesc *desc, ThreadContext *tc, VPtr<> start, + typename OS::size_t length) +{ + // Even if the system is currently not capable of recycling physical + // pages, there is no reason we can't unmap them so that we trigger + // appropriate seg faults when the application mistakenly tries to + // access them again. + auto p = tc->getProcessPtr(); + + if (p->pTable->pageOffset(start)) + return -EINVAL; + + length = roundUp(length, p->pTable->pageSize()); + + p->memState->unmapRegion(start, length); + + return 0; +} + } // namespace gem5 #endif // __SIM_SYSCALL_EMUL_HH__