Hi everyone,

One very major problem I had in running one of my binaries concerned the 'brk' system call. When a program calls this to reduce the brk point, then some time later calls it again to increase the brk point, the page tables will have already been allocated in M5 and there could already be data at these new addresses in memory.

Although this is not usually a problem, in my version of glibc, on a calloc, the kernel is assumed to have already cleared this data out so the library doesn't do it. I've now implemented this in the simulator, which is covered by this patch.

This bug took me a long time to find. It only shows up on this sequence of events:

* Data is written to some area of memory just below brk point
* The brk point is reduced (via the brk system call) so that these addresses are now not in user space * Later, the brk point is increased again so these addresses go back into user space * The program calls calloc which returns these addresses but doesn't clear them because it assumes the kernel has already done this
* The program then uses the new memory assuming it is zero

This patch adds a zero function to PhysicalMemory and uses it on a brk system call if the page tables have already been allocated (i.e. the addresses have already been used).

This may not be the best way to implement this, I'm not sure what you all think, so any commments or corrections are welcome.

Cheers
Tim

--
The University of Edinburgh is a charitable body, registered in
Scotland, with registration number SC005336.

diff -r 55a8fe0bd3b3 -r 992cb1c04dca src/mem/physical.cc
--- a/src/mem/physical.cc	Tue Aug 25 12:10:26 2009 +0100
+++ b/src/mem/physical.cc	Tue Aug 25 13:55:24 2009 +0100
@@ -452,6 +452,13 @@
 }
 
 void
+PhysicalMemory::zero(Addr addr, unsigned int size)
+{
+  uint8_t *hostAddr = pmemAddr + addr - start();
+  memset(hostAddr, 0, size);
+}
+
+void
 PhysicalMemory::serialize(ostream &os)
 {
     if (!pmemAddr)
diff -r 55a8fe0bd3b3 -r 992cb1c04dca src/mem/physical.hh
--- a/src/mem/physical.hh	Tue Aug 25 12:10:26 2009 +0100
+++ b/src/mem/physical.hh	Tue Aug 25 13:55:24 2009 +0100
@@ -173,6 +173,7 @@
     virtual Port *getPort(const std::string &if_name, int idx = -1);
     void virtual init();
     unsigned int drain(Event *de);
+    void zero(Addr addr, unsigned int size);
 
   protected:
     Tick doAtomicAccess(PacketPtr pkt);
diff -r 55a8fe0bd3b3 -r 992cb1c04dca src/sim/syscall_emul.cc
--- a/src/sim/syscall_emul.cc	Tue Aug 25 12:10:26 2009 +0100
+++ b/src/sim/syscall_emul.cc	Tue Aug 25 13:55:24 2009 +0100
@@ -41,6 +41,7 @@
 #include "cpu/thread_context.hh"
 #include "cpu/base.hh"
 #include "mem/page_table.hh"
+#include "mem/physical.hh"
 #include "sim/process.hh"
 #include "sim/system.hh"
 
@@ -138,12 +139,19 @@
         return p->brk_point;
 
     if (new_brk > p->brk_point) {
+        Addr paddr;
+
         // might need to allocate some new pages
         for (ChunkGenerator gen(p->brk_point, new_brk - p->brk_point,
                                 VMPageSize); !gen.done(); gen.next()) {
-            if (!p->pTable->translate(gen.addr()))
+            if (!p->pTable->translate(gen.addr(), paddr))
                 p->pTable->allocate(roundDown(gen.addr(), VMPageSize),
                                     VMPageSize);
+
+            // if the address is already there, zero it out
+            else {
+              p->system->physmem->zero(paddr, VMPageSize);
+            }
         }
     }
 
_______________________________________________
m5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/m5-dev

Reply via email to