From 8d29bda74211f4ff1804aeeb05b2795b549036f7 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Mon, 23 May 2011 14:29:23 -0700 Subject: [PATCH] syscall emul: fix Power Linux mmap constant, plus other cleanup We were getting a spurious warning in the regressions that turned out to be due to having the wrong value for TGT_MAP_ANONYMOUS for Power Linux, but in the process of tracking it down I ended up doing some cleanup of the mmap handling in general. --- src/arch/power/linux/linux.hh | 2 +- src/sim/process.cc | 6 +++--- src/sim/syscall_emul.hh | 31 ++++++++++++++++++------------- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/arch/power/linux/linux.hh b/src/arch/power/linux/linux.hh index c681c8baf..1bfc9cbd8 100644 --- a/src/arch/power/linux/linux.hh +++ b/src/arch/power/linux/linux.hh @@ -126,7 +126,7 @@ class PowerLinux : public Linux //@} /// For mmap(). - static const unsigned TGT_MAP_ANONYMOUS = 0x800; + static const unsigned TGT_MAP_ANONYMOUS = 0x20; //@{ /// ioctl() command codes. diff --git a/src/sim/process.cc b/src/sim/process.cc index 9a9527664..28142d731 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -313,7 +313,7 @@ Process::free_fd(int tgt_fd) int Process::sim_fd(int tgt_fd) { - if (tgt_fd > MAX_FD) + if (tgt_fd < 0 || tgt_fd > MAX_FD) return -1; return fd_map[tgt_fd].fd; @@ -322,8 +322,8 @@ Process::sim_fd(int tgt_fd) Process::FdMap * Process::sim_fd_obj(int tgt_fd) { - if (tgt_fd > MAX_FD) - panic("sim_fd_obj called in fd out of range."); + if (tgt_fd < 0 || tgt_fd > MAX_FD) + return NULL; return &fd_map[tgt_fd]; } diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index e685a0f30..d119adc24 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -989,13 +989,8 @@ writevFunc(SyscallDesc *desc, int callnum, LiveProcess *process, /// We don't really handle mmap(). If the target is mmaping an /// anonymous region or /dev/zero, we can get away with doing basically /// nothing (since memory is initialized to zero and the simulator -/// doesn't really check addresses anyway). Always print a warning, -/// since this could be seriously broken if we're not mapping -/// /dev/zero. -// -/// Someday we should explicitly check for /dev/zero in open, flag the -/// file descriptor, and fail (or implement!) a non-anonymous mmap to -/// anything else. +/// doesn't really check addresses anyway). +/// template SyscallReturn mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) @@ -1005,9 +1000,24 @@ mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) uint64_t length = p->getSyscallArg(tc, index); index++; // int prot = p->getSyscallArg(tc, index); int flags = p->getSyscallArg(tc, index); - int fd = p->sim_fd(p->getSyscallArg(tc, index)); + int tgt_fd = p->getSyscallArg(tc, index); // int offset = p->getSyscallArg(tc, index); + if (!(flags & OS::TGT_MAP_ANONYMOUS)) { + Process::FdMap *fd_map = p->sim_fd_obj(tgt_fd); + if (!fd_map || fd_map->fd < 0) { + warn("mmap failing: target fd %d is not valid\n", tgt_fd); + return -EBADF; + } + + if (fd_map->filename != "/dev/zero") { + // This is very likely broken, but leave a warning here + // (rather than panic) in case /dev/zero is known by + // another name on some platform + warn("allowing mmap of file %s; mmap not supported on files" + " other than /dev/zero\n", fd_map->filename); + } + } if ((start % TheISA::VMPageSize) != 0 || (length % TheISA::VMPageSize) != 0) { @@ -1032,11 +1042,6 @@ mmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc) } p->pTable->allocate(start, length); - if (!(flags & OS::TGT_MAP_ANONYMOUS)) { - warn("allowing mmap of file @ fd %d. " - "This will break if not /dev/zero.", fd); - } - return start; }