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 <giacomo.travaglini@arm.com> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/51489 Reviewed-by: Jason Lowe-Power <power.jg@gmail.com> Reviewed-by: Gabe Black <gabe.black@gmail.com> Maintainer: Jason Lowe-Power <power.jg@gmail.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -136,7 +136,7 @@ static SyscallDescTable<EmuFreebsd::SyscallABI64> syscallDescs64 = {
|
||||
{ 4, "write", writeFunc<ArmFreebsd64> },
|
||||
{ 17, "obreak", brkFunc },
|
||||
{ 54, "ioctl", ioctlFunc<ArmFreebsd64> },
|
||||
{ 58, "readlink", readlinkFunc },
|
||||
{ 58, "readlink", readlinkFunc<ArmFreebsd64> },
|
||||
{ 117, "getrusage", getrusageFunc<ArmFreebsd64> },
|
||||
{ 189, "fstat", fstatFunc<ArmFreebsd64> },
|
||||
#if !defined ( __GNU_LIBRARY__ )
|
||||
|
||||
@@ -216,13 +216,13 @@ class SyscallTable32 : public SyscallDescTable<EmuLinux::SyscallABI32>
|
||||
{ base + 81, "setgroups" },
|
||||
{ base + 82, "reserved#82" },
|
||||
{ base + 83, "symlink" },
|
||||
{ base + 85, "readlink", readlinkFunc },
|
||||
{ base + 85, "readlink", readlinkFunc<ArmLinux32> },
|
||||
{ base + 86, "uselib" },
|
||||
{ base + 87, "swapon" },
|
||||
{ base + 88, "reboot" },
|
||||
{ base + 89, "readdir" },
|
||||
{ base + 90, "mmap", mmapFunc<ArmLinux32> },
|
||||
{ base + 91, "munmap", munmapFunc },
|
||||
{ base + 91, "munmap", munmapFunc<ArmLinux32> },
|
||||
{ base + 92, "truncate", truncateFunc },
|
||||
{ base + 93, "ftruncate", ftruncateFunc },
|
||||
{ base + 94, "fchmod" },
|
||||
@@ -413,9 +413,9 @@ class SyscallTable32 : public SyscallDescTable<EmuLinux::SyscallABI32>
|
||||
{ base + 287, "getpeername" },
|
||||
{ base + 288, "socketpair" },
|
||||
{ base + 289, "send" },
|
||||
{ base + 290, "sendto", sendtoFunc },
|
||||
{ base + 290, "sendto", sendtoFunc<ArmLinux32> },
|
||||
{ base + 291, "recv" },
|
||||
{ base + 292, "recvfrom", recvfromFunc },
|
||||
{ base + 292, "recvfrom", recvfromFunc<ArmLinux32> },
|
||||
{ base + 293, "shutdown" },
|
||||
{ base + 294, "setsockopt" },
|
||||
{ base + 295, "getsockopt" },
|
||||
@@ -708,8 +708,8 @@ class SyscallTable64 : public SyscallDescTable<EmuLinux::SyscallABI64>
|
||||
{ base + 203, "connect" },
|
||||
{ base + 204, "getsockname" },
|
||||
{ base + 205, "getpeername" },
|
||||
{ base + 206, "sendto", sendtoFunc },
|
||||
{ base + 207, "recvfrom", recvfromFunc },
|
||||
{ base + 206, "sendto", sendtoFunc<ArmLinux64> },
|
||||
{ base + 207, "recvfrom", recvfromFunc<ArmLinux64> },
|
||||
{ base + 208, "setsockopt" },
|
||||
{ base + 209, "getsockopt" },
|
||||
{ base + 210, "shutdown" },
|
||||
@@ -717,7 +717,7 @@ class SyscallTable64 : public SyscallDescTable<EmuLinux::SyscallABI64>
|
||||
{ base + 212, "recvmsg" },
|
||||
{ base + 213, "readahead" },
|
||||
{ base + 214, "brk", brkFunc },
|
||||
{ base + 215, "munmap", munmapFunc },
|
||||
{ base + 215, "munmap", munmapFunc<ArmLinux64> },
|
||||
{ base + 216, "mremap", mremapFunc<ArmLinux64> },
|
||||
{ base + 217, "add_key" },
|
||||
{ base + 218, "request_key" },
|
||||
@@ -769,7 +769,7 @@ class SyscallTable64 : public SyscallDescTable<EmuLinux::SyscallABI64>
|
||||
{ base + 1032, "lchown" },
|
||||
{ base + 1033, "access", accessFunc },
|
||||
{ base + 1034, "rename", renameFunc },
|
||||
{ base + 1035, "readlink", readlinkFunc },
|
||||
{ base + 1035, "readlink", readlinkFunc<ArmLinux64> },
|
||||
{ base + 1036, "symlink" },
|
||||
{ base + 1037, "utimes" },
|
||||
{ base + 1038, "stat64", stat64Func<ArmLinux64> },
|
||||
|
||||
@@ -243,13 +243,13 @@ SyscallDescTable<MipsISA::SEWorkload::SyscallABI> EmuLinux::syscallDescs = {
|
||||
{ 4082, "reserved#82" },
|
||||
{ 4083, "symlink" },
|
||||
{ 4084, "unused#84" },
|
||||
{ 4085, "readlink", readlinkFunc },
|
||||
{ 4085, "readlink", readlinkFunc<MipsLinux> },
|
||||
{ 4086, "uselib" },
|
||||
{ 4087, "swapon", gethostnameFunc },
|
||||
{ 4088, "reboot" },
|
||||
{ 4089, "readdir" },
|
||||
{ 4090, "mmap", mmapFunc<MipsLinux> },
|
||||
{ 4091, "munmap",munmapFunc },
|
||||
{ 4091, "munmap",munmapFunc<MipsLinux> },
|
||||
{ 4092, "truncate", truncateFunc },
|
||||
{ 4093, "ftruncate", ftruncateFunc },
|
||||
{ 4094, "fchmod", fchmodFunc<MipsLinux> },
|
||||
|
||||
@@ -192,13 +192,13 @@ SyscallDescTable<PowerISA::SEWorkload::SyscallABI> EmuLinux::syscallDescs = {
|
||||
{ 82, "reserved#82" },
|
||||
{ 83, "symlink" },
|
||||
{ 84, "unused#84" },
|
||||
{ 85, "readlink", readlinkFunc },
|
||||
{ 85, "readlink", readlinkFunc<PowerLinux> },
|
||||
{ 86, "uselib" },
|
||||
{ 87, "swapon", gethostnameFunc },
|
||||
{ 88, "reboot" },
|
||||
{ 89, "readdir" },
|
||||
{ 90, "mmap", mmapFunc<PowerLinux> },
|
||||
{ 91, "munmap",munmapFunc },
|
||||
{ 91, "munmap",munmapFunc<PowerLinux> },
|
||||
{ 92, "truncate", truncateFunc },
|
||||
{ 93, "ftruncate", ftruncateFunc },
|
||||
{ 94, "fchmod" },
|
||||
|
||||
@@ -338,7 +338,7 @@ SyscallDescTable<SEWorkload::SyscallABI> EmuLinux::syscallDescs64 = {
|
||||
{ 212, "recvmsg" },
|
||||
{ 213, "readahead" },
|
||||
{ 214, "brk", brkFunc },
|
||||
{ 215, "munmap", munmapFunc },
|
||||
{ 215, "munmap", munmapFunc<RiscvLinux64> },
|
||||
{ 216, "mremap", mremapFunc<RiscvLinux64> },
|
||||
{ 217, "add_key" },
|
||||
{ 218, "request_key" },
|
||||
@@ -406,7 +406,7 @@ SyscallDescTable<SEWorkload::SyscallABI> EmuLinux::syscallDescs64 = {
|
||||
{ 1032, "lchown" },
|
||||
{ 1033, "access", accessFunc },
|
||||
{ 1034, "rename", renameFunc },
|
||||
{ 1035, "readlink", readlinkFunc },
|
||||
{ 1035, "readlink", readlinkFunc<RiscvLinux64> },
|
||||
{ 1036, "symlink" },
|
||||
{ 1037, "utimes", utimesFunc<RiscvLinux64> },
|
||||
{ 1038, "stat", stat64Func<RiscvLinux64> },
|
||||
@@ -669,7 +669,7 @@ SyscallDescTable<SEWorkload::SyscallABI> EmuLinux::syscallDescs32 = {
|
||||
{ 212, "recvmsg" },
|
||||
{ 213, "readahead" },
|
||||
{ 214, "brk", brkFunc },
|
||||
{ 215, "munmap", munmapFunc },
|
||||
{ 215, "munmap", munmapFunc<RiscvLinux32> },
|
||||
{ 216, "mremap", mremapFunc<RiscvLinux32> },
|
||||
{ 217, "add_key" },
|
||||
{ 218, "request_key" },
|
||||
@@ -737,7 +737,7 @@ SyscallDescTable<SEWorkload::SyscallABI> EmuLinux::syscallDescs32 = {
|
||||
{ 1032, "lchown" },
|
||||
{ 1033, "access", accessFunc },
|
||||
{ 1034, "rename", renameFunc },
|
||||
{ 1035, "readlink", readlinkFunc },
|
||||
{ 1035, "readlink", readlinkFunc<RiscvLinux32> },
|
||||
{ 1036, "symlink" },
|
||||
{ 1037, "utimes", utimesFunc<RiscvLinux32> },
|
||||
{ 1038, "stat", statFunc<RiscvLinux32> },
|
||||
|
||||
@@ -143,7 +143,7 @@ SyscallDescTable<SEWorkload::SyscallABI32> EmuLinux::syscall32Descs = {
|
||||
{ 55, "reboot" }, // 32 bit
|
||||
{ 56, "mmap2" }, // 32 bit
|
||||
{ 57, "symlink" },
|
||||
{ 58, "readlink", readlinkFunc }, // 32 bit
|
||||
{ 58, "readlink", readlinkFunc<Sparc32Linux> }, // 32 bit
|
||||
{ 59, "execve" }, // 32 bit
|
||||
{ 60, "umask" }, // 32 bit
|
||||
{ 61, "chroot" },
|
||||
@@ -158,7 +158,7 @@ SyscallDescTable<SEWorkload::SyscallABI32> EmuLinux::syscall32Descs = {
|
||||
{ 70, "getegid32" },
|
||||
{ 71, "mmap", mmapFunc<Sparc32Linux> },
|
||||
{ 72, "setreuid32" },
|
||||
{ 73, "munmap", munmapFunc },
|
||||
{ 73, "munmap", munmapFunc<Sparc32Linux> },
|
||||
{ 74, "mprotect", ignoreFunc },
|
||||
{ 75, "madvise" },
|
||||
{ 76, "vhangup" },
|
||||
@@ -446,7 +446,7 @@ SyscallDescTable<SEWorkload::SyscallABI64> EmuLinux::syscallDescs = {
|
||||
{ 55, "reboot" },
|
||||
{ 56, "mmap2" },
|
||||
{ 57, "symlink" },
|
||||
{ 58, "readlink", readlinkFunc },
|
||||
{ 58, "readlink", readlinkFunc<SparcLinux> },
|
||||
{ 59, "execve" },
|
||||
{ 60, "umask" },
|
||||
{ 61, "chroot" },
|
||||
@@ -461,7 +461,7 @@ SyscallDescTable<SEWorkload::SyscallABI64> EmuLinux::syscallDescs = {
|
||||
{ 70, "getegid32" },
|
||||
{ 71, "mmap", mmapFunc<SparcLinux> },
|
||||
{ 72, "setreuid32" },
|
||||
{ 73, "munmap", munmapFunc },
|
||||
{ 73, "munmap", munmapFunc<SparcLinux> },
|
||||
{ 74, "mprotect", ignoreFunc },
|
||||
{ 75, "madvise" },
|
||||
{ 76, "vhangup" },
|
||||
|
||||
@@ -124,13 +124,13 @@ SyscallDescTable<EmuLinux::SyscallABI32> EmuLinux::syscallDescs32 = {
|
||||
{ 82, "select", selectFunc<X86Linux32> },
|
||||
{ 83, "symlink" },
|
||||
{ 84, "oldlstat" },
|
||||
{ 85, "readlink", readlinkFunc },
|
||||
{ 85, "readlink", readlinkFunc<X86Linux32> },
|
||||
{ 86, "uselib" },
|
||||
{ 87, "swapon" },
|
||||
{ 88, "reboot" },
|
||||
{ 89, "readdir" },
|
||||
{ 90, "mmap" },
|
||||
{ 91, "munmap", munmapFunc },
|
||||
{ 91, "munmap", munmapFunc<X86Linux32> },
|
||||
{ 92, "truncate", truncateFunc },
|
||||
{ 93, "ftruncate", ftruncateFunc },
|
||||
{ 94, "fchmod" },
|
||||
@@ -352,7 +352,7 @@ SyscallDescTable<EmuLinux::SyscallABI32> EmuLinux::syscallDescs32 = {
|
||||
{ 302, "renameat" },
|
||||
{ 303, "linkat" },
|
||||
{ 304, "symlinkat" },
|
||||
{ 305, "readlinkat", readlinkFunc },
|
||||
{ 305, "readlinkat", readlinkFunc<X86Linux32> },
|
||||
{ 306, "fchmodat" },
|
||||
{ 307, "faccessat" },
|
||||
{ 308, "pselect6" },
|
||||
|
||||
@@ -50,7 +50,7 @@ SyscallDescTable<EmuLinux::SyscallABI64> EmuLinux::syscallDescs64 = {
|
||||
{ 8, "lseek", lseekFunc },
|
||||
{ 9, "mmap", mmapFunc<X86Linux64> },
|
||||
{ 10, "mprotect", ignoreFunc },
|
||||
{ 11, "munmap", munmapFunc },
|
||||
{ 11, "munmap", munmapFunc<X86Linux64> },
|
||||
{ 12, "brk", brkFunc },
|
||||
{ 13, "rt_sigaction", ignoreWarnOnceFunc },
|
||||
{ 14, "rt_sigprocmask", ignoreWarnOnceFunc },
|
||||
@@ -83,8 +83,8 @@ SyscallDescTable<EmuLinux::SyscallABI64> EmuLinux::syscallDescs64 = {
|
||||
{ 41, "socket", socketFunc<X86Linux64> },
|
||||
{ 42, "connect", connectFunc },
|
||||
{ 43, "accept", acceptFunc<X86Linux64> },
|
||||
{ 44, "sendto", sendtoFunc },
|
||||
{ 45, "recvfrom", recvfromFunc },
|
||||
{ 44, "sendto", sendtoFunc<X86Linux64> },
|
||||
{ 45, "recvfrom", recvfromFunc<X86Linux64> },
|
||||
{ 46, "sendmsg", sendmsgFunc },
|
||||
{ 47, "recvmsg", recvmsgFunc },
|
||||
{ 48, "shutdown", shutdownFunc },
|
||||
@@ -132,7 +132,7 @@ SyscallDescTable<EmuLinux::SyscallABI64> EmuLinux::syscallDescs64 = {
|
||||
{ 86, "link", linkFunc },
|
||||
{ 87, "unlink", unlinkFunc },
|
||||
{ 88, "symlink", symlinkFunc },
|
||||
{ 89, "readlink", readlinkFunc },
|
||||
{ 89, "readlink", readlinkFunc<X86Linux64> },
|
||||
{ 90, "chmod", ignoreFunc },
|
||||
{ 91, "fchmod" },
|
||||
{ 92, "chown" },
|
||||
@@ -314,7 +314,7 @@ SyscallDescTable<EmuLinux::SyscallABI64> EmuLinux::syscallDescs64 = {
|
||||
{ 264, "renameat" },
|
||||
{ 265, "linkat" },
|
||||
{ 266, "symlinkat" },
|
||||
{ 267, "readlinkat", readlinkFunc },
|
||||
{ 267, "readlinkat", readlinkFunc<X86Linux64> },
|
||||
{ 268, "fchmodat" },
|
||||
{ 269, "faccessat" },
|
||||
{ 270, "pselect6" },
|
||||
|
||||
@@ -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<SocketFDEntry>((*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<SocketFDEntry>((*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,
|
||||
|
||||
@@ -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 <class OS>
|
||||
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 <class OS>
|
||||
SyscallReturn
|
||||
readlinkFunc(SyscallDesc *desc, ThreadContext *tc,
|
||||
VPtr<> pathname, VPtr<> buf_ptr,
|
||||
typename OS::size_t bufsiz)
|
||||
{
|
||||
return readlinkatFunc<OS>(desc, tc, OS::TGT_AT_FDCWD,
|
||||
pathname, buf_ptr, bufsiz);
|
||||
}
|
||||
|
||||
/// Target renameat() handler.
|
||||
@@ -1625,7 +1664,8 @@ fstatfsFunc(SyscallDesc *desc, ThreadContext *tc,
|
||||
template <class OS>
|
||||
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 <class OS>
|
||||
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 <class OS>
|
||||
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 <class OS>
|
||||
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<SocketFDEntry>((*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 <typename OS>
|
||||
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<SocketFDEntry>((*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 <typename OS>
|
||||
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__
|
||||
|
||||
Reference in New Issue
Block a user