summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChris Adeniyi-Jones <Chris.Adeniyi-Jones@arm.com>2014-01-24 15:29:30 -0600
committerChris Adeniyi-Jones <Chris.Adeniyi-Jones@arm.com>2014-01-24 15:29:30 -0600
commit7f835a59f1c342eb1c170973ad53c493cc38e978 (patch)
treece6e42722c25177fdee4175a7607e4dde96f8b0c /src
parent904872a01a81ef5ee3f20e42c0657e35a491d6c9 (diff)
downloadgem5-7f835a59f1c342eb1c170973ad53c493cc38e978.tar.xz
sim: Add openat/fstatat syscalls and fix mremap
This patch adds support for the openat and fstatat syscalls and broadens the support for mremap to make it work on OS X.
Diffstat (limited to 'src')
-rw-r--r--src/kern/linux/linux.hh6
-rw-r--r--src/sim/syscall_emul.hh123
2 files changed, 111 insertions, 18 deletions
diff --git a/src/kern/linux/linux.hh b/src/kern/linux/linux.hh
index 1fcd80444..5e929f1c0 100644
--- a/src/kern/linux/linux.hh
+++ b/src/kern/linux/linux.hh
@@ -227,6 +227,12 @@ class Linux : public OperatingSystem
static const unsigned TGT_EWOULDBLOCK = TGT_EAGAIN;
static const unsigned TGT_FUTEX_PRIVATE_FLAG = 128;
+ // for *at syscalls
+ static const int TGT_AT_FDCWD = -100;
+
+ // for MREMAP
+ static const unsigned TGT_MREMAP_MAYMOVE = 0x1;
+ static const unsigned TGT_MREMAP_FIXED = 0x2;
}; // class Linux
#endif // __LINUX_HH__
diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh
index 364b66c0a..ac01ba1e8 100644
--- a/src/sim/syscall_emul.hh
+++ b/src/sim/syscall_emul.hh
@@ -1,4 +1,16 @@
/*
+ * Copyright (c) 2012-2013 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
@@ -600,15 +612,13 @@ ioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
return -ENOTTY;
}
-/// Target open() handler.
template <class OS>
-SyscallReturn
+static SyscallReturn
openFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
- ThreadContext *tc)
+ ThreadContext *tc, int index)
{
std::string path;
- int index = 0;
if (!tc->getMemProxy().tryReadString(path,
process->getSyscallArg(tc, index)))
return -EFAULT;
@@ -664,6 +674,28 @@ openFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
return process->alloc_fd(fd, path.c_str(), hostFlags, mode, false);
}
+/// Target open() handler.
+template <class OS>
+SyscallReturn
+openFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+ ThreadContext *tc)
+{
+ return openFunc<OS>(desc, callnum, process, tc, 0);
+}
+
+/// Target openat() handler.
+template <class OS>
+SyscallReturn
+openatFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
+ ThreadContext *tc)
+{
+ int index = 0;
+ int dirfd = process->getSyscallArg(tc, index);
+ if (dirfd != OS::TGT_AT_FDCWD)
+ warn("openat: first argument not AT_FDCWD; unlikely to work");
+ return openFunc<OS>(desc, callnum, process, tc, 1);
+}
+
/// Target sysinfo() handler.
template <class OS>
SyscallReturn
@@ -752,40 +784,58 @@ mremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *
uint64_t old_length = process->getSyscallArg(tc, index);
uint64_t new_length = process->getSyscallArg(tc, index);
uint64_t flags = process->getSyscallArg(tc, index);
+ uint64_t provided_address = 0;
+ bool use_provided_address = flags & OS::TGT_MREMAP_FIXED;
+
+ if (use_provided_address)
+ provided_address = process->getSyscallArg(tc, index);
if ((start % TheISA::VMPageSize != 0) ||
- (new_length % TheISA::VMPageSize != 0)) {
+ (new_length % TheISA::VMPageSize != 0) ||
+ (provided_address % TheISA::VMPageSize != 0)) {
warn("mremap failing: arguments not page aligned");
return -EINVAL;
}
if (new_length > old_length) {
- if ((start + old_length) == process->mmap_end) {
+ if ((start + old_length) == process->mmap_end &&
+ (!use_provided_address || provided_address == start)) {
uint64_t diff = new_length - old_length;
process->allocateMem(process->mmap_end, diff);
process->mmap_end += diff;
return start;
} else {
- // sys/mman.h defined MREMAP_MAYMOVE
- if (!(flags & 1)) {
+ if (!use_provided_address && !(flags & OS::TGT_MREMAP_MAYMOVE)) {
warn("can't remap here and MREMAP_MAYMOVE flag not set\n");
return -ENOMEM;
} else {
- process->pTable->remap(start, old_length, process->mmap_end);
- warn("mremapping to totally new vaddr %08p-%08p, adding %d\n",
- process->mmap_end, process->mmap_end + new_length, new_length);
- start = process->mmap_end;
+ uint64_t new_start = use_provided_address ?
+ provided_address : process->mmap_end;
+ process->pTable->remap(start, old_length, new_start);
+ warn("mremapping to new vaddr %08p-%08p, adding %d\n",
+ new_start, new_start + new_length,
+ new_length - old_length);
// add on the remaining unallocated pages
- process->allocateMem(start + old_length,
- new_length - old_length);
- process->mmap_end += new_length;
- warn("returning %08p as start\n", start);
- return start;
+ process->allocateMem(new_start + old_length,
+ new_length - old_length,
+ use_provided_address /* clobber */);
+ if (!use_provided_address)
+ process->mmap_end += new_length;
+ if (use_provided_address &&
+ new_start + new_length > process->mmap_end) {
+ // something fishy going on here, at least notify the user
+ // @todo: increase mmap_end?
+ warn("mmap region limit exceeded with MREMAP_FIXED\n");
+ }
+ warn("returning %08p as start\n", new_start);
+ return new_start;
}
}
} else {
+ if (use_provided_address && provided_address != start)
+ process->pTable->remap(start, new_length, provided_address);
process->pTable->unmap(start + new_length, old_length - new_length);
- return start;
+ return use_provided_address ? provided_address : start;
}
}
@@ -853,6 +903,43 @@ stat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
}
+/// Target fstatat64() handler.
+template <class OS>
+SyscallReturn
+fstatat64Func(SyscallDesc *desc, int callnum, LiveProcess *process,
+ ThreadContext *tc)
+{
+ int index = 0;
+ int dirfd = process->getSyscallArg(tc, index);
+ if (dirfd != OS::TGT_AT_FDCWD)
+ warn("openat: first argument not AT_FDCWD; unlikely to work");
+
+ std::string path;
+ if (!tc->getMemProxy().tryReadString(path,
+ process->getSyscallArg(tc, index)))
+ return -EFAULT;
+ Addr bufPtr = process->getSyscallArg(tc, index);
+
+ // Adjust path for current working directory
+ path = process->fullPath(path);
+
+#if NO_STAT64
+ struct stat hostBuf;
+ int result = stat(path.c_str(), &hostBuf);
+#else
+ struct stat64 hostBuf;
+ int result = stat64(path.c_str(), &hostBuf);
+#endif
+
+ if (result < 0)
+ return -errno;
+
+ copyOutStat64Buf<OS>(tc->getMemProxy(), bufPtr, &hostBuf);
+
+ return 0;
+}
+
+
/// Target fstat64() handler.
template <class OS>
SyscallReturn