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:
Giacomo Travaglini
2021-10-12 17:00:16 +01:00
parent 43910b5312
commit 37495f8823
10 changed files with 220 additions and 236 deletions

View File

@@ -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__ )

View File

@@ -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> },

View File

@@ -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> },

View File

@@ -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" },

View File

@@ -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> },

View File

@@ -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" },

View File

@@ -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" },

View File

@@ -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" },

View File

@@ -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,

View File

@@ -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__