summaryrefslogtreecommitdiff
path: root/src/sim/syscall_emul.cc
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 /src/sim/syscall_emul.cc
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.
Diffstat (limited to 'src/sim/syscall_emul.cc')
-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);
+ }
+ }
}
}