+/// Target mremap() handler.
+template <class OS>
+SyscallReturn
+mremapFunc(SyscallDesc *desc, int callnum, LiveProcess *process, ThreadContext *tc)
+{
+ int index = 0;
+ Addr start = process->getSyscallArg(tc, index);
+ uint64_t old_length = process->getSyscallArg(tc, index);
+ uint64_t new_length = process->getSyscallArg(tc, index);
+ uint64_t flags = process->getSyscallArg(tc, index);
+
+ if ((start % TheISA::VMPageSize != 0) ||
+ (new_length % TheISA::VMPageSize != 0)) {
+ warn("mremap failing: arguments not page aligned");
+ return -EINVAL;
+ }
+
+ if (new_length > old_length) {
+ if ((start + old_length) == process->mmap_end) {
+ uint64_t diff = new_length - old_length;
+ process->pTable->allocate(process->mmap_end, diff);
+ process->mmap_end += diff;
+ return start;
+ } else {
+ // sys/mman.h defined MREMAP_MAYMOVE
+ if (!(flags & 1)) {
+ 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;
+ // add on the remaining unallocated pages
+ process->pTable->allocate(start + old_length, new_length - old_length);
+ process->mmap_end += new_length;
+ warn("returning %08p as start\n", start);
+ return start;
+ }
+ }
+ } else {
+ process->pTable->deallocate(start + new_length, old_length -
+ new_length);
+ return start;
+ }
+}