summaryrefslogtreecommitdiff
path: root/src/sim
diff options
context:
space:
mode:
Diffstat (limited to 'src/sim')
-rw-r--r--src/sim/syscall_emul.hh20
1 files changed, 15 insertions, 5 deletions
diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh
index 7efd7c7e6..fa0959f0e 100644
--- a/src/sim/syscall_emul.hh
+++ b/src/sim/syscall_emul.hh
@@ -932,6 +932,8 @@ mremapFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
if ((start + old_length) == mmap_end &&
(!use_provided_address || provided_address == start)) {
+ // This case cannot occur when growing downward, as
+ // start is greater than or equal to mmap_end.
uint64_t diff = new_length - old_length;
process->allocateMem(mmap_end, diff);
mem_state->setMmapEnd(mmap_end + diff);
@@ -941,8 +943,15 @@ mremapFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
warn("can't remap here and MREMAP_MAYMOVE flag not set\n");
return -ENOMEM;
} else {
- uint64_t new_start = use_provided_address ?
- provided_address : mmap_end;
+ uint64_t new_start = provided_address;
+ if (!use_provided_address) {
+ new_start = process->mmapGrowsDown() ?
+ mmap_end - new_length : mmap_end;
+ mmap_end = process->mmapGrowsDown() ?
+ new_start : mmap_end + new_length;
+ mem_state->setMmapEnd(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,
@@ -951,10 +960,11 @@ mremapFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc)
process->allocateMem(new_start + old_length,
new_length - old_length,
use_provided_address /* clobber */);
- if (!use_provided_address)
- mem_state->setMmapEnd(mmap_end + new_length);
if (use_provided_address &&
- new_start + new_length > mem_state->getMmapEnd()) {
+ ((new_start + new_length > mem_state->getMmapEnd() &&
+ !process->mmapGrowsDown()) ||
+ (new_start < mem_state->getMmapEnd() &&
+ process->mmapGrowsDown()))) {
// something fishy going on here, at least notify the user
// @todo: increase mmap_end?
warn("mmap region limit exceeded with MREMAP_FIXED\n");