summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimothy M. Jones <tjones1@inf.ed.ac.uk>2009-10-24 10:53:58 -0700
committerTimothy M. Jones <tjones1@inf.ed.ac.uk>2009-10-24 10:53:58 -0700
commit03da1e53c24aa86a3b04216c3d2d002fd9020ea0 (patch)
tree8b562fe53646a789df61bf514669a1b60bd08777
parentcc21f862e2d6ad6ba8d5332d6bbc05e58e55bfa0 (diff)
downloadgem5-03da1e53c24aa86a3b04216c3d2d002fd9020ea0.tar.xz
syscall: Zero out memory that already exists during the brk system call.
Glibc often assumes that memory it receives from the kernel after a brk system call will contain only zeros. This is important during a calloc, because it won't clear the new memory itself. In the simulator, if the new page exists, it will be cleared using this patch, to mimic the kernel's functionality.
-rw-r--r--src/sim/syscall_emul.cc18
1 files changed, 18 insertions, 0 deletions
diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc
index 9a797bcdb..13ad04311 100644
--- a/src/sim/syscall_emul.cc
+++ b/src/sim/syscall_emul.cc
@@ -144,6 +144,24 @@ brkFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
if (!p->pTable->translate(gen.addr()))
p->pTable->allocate(roundDown(gen.addr(), VMPageSize),
VMPageSize);
+
+ // if the address is already there, zero it out
+ else {
+ uint8_t zero = 0;
+ TranslatingPort *tp = tc->getMemPort();
+
+ // split non-page aligned accesses
+ Addr next_page = roundUp(gen.addr(), VMPageSize);
+ uint32_t size_needed = next_page - gen.addr();
+ tp->memsetBlob(gen.addr(), zero, size_needed);
+ if (gen.addr() + VMPageSize > next_page &&
+ next_page < new_brk &&
+ p->pTable->translate(next_page))
+ {
+ size_needed = VMPageSize - size_needed;
+ tp->memsetBlob(next_page, zero, size_needed);
+ }
+ }
}
}