The attached patch introduces new internal calls which give
better coordination with explicit user stack switching:
   VG_USERREQ__STACK_SWITCH   notify V of explicit switch
   VG_USERREQ__STACK_DEREGADDR   de-register by address (not id)
The patch is against valgrind-3.2.3.

The patch also strengthens the logic of VG_(switch_stack):
   the new stack always becomes current_stack
   allow old and new to be the same

An example implementation of longjmp() for x86 is included.
Perhaps VEX could be enhanced later so that "movl ...,%esp"
(or any non-incremental operation with stack pointer as destination)
generated VG_USERREQ__STACK_SWITCH automatically, but not now.

-- 
John Reiser, [EMAIL PROTECTED]
diff -Nur valgrind-3.2.3/coregrind/m_scheduler/scheduler.c valgrind-3.2.3.new/coregrind/m_scheduler/scheduler.c
--- valgrind-3.2.3/coregrind/m_scheduler/scheduler.c	2007-01-07 23:43:14.000000000 -0800
+++ valgrind-3.2.3.new/coregrind/m_scheduler/scheduler.c	2007-11-08 09:26:19.000000000 -0800
@@ -1205,6 +1205,11 @@
          SET_CLREQ_RETVAL( tid, sid );
          break; }
 
+      case VG_USERREQ__STACK_DEREGADDR: {
+         VG_(deregaddr_stack)((Addr)arg[1]);
+         SET_CLREQ_RETVAL( tid, 0 );     /* return value is meaningless */
+      }
+
       case VG_USERREQ__STACK_DEREGISTER: {
          VG_(deregister_stack)(arg[1]);
          SET_CLREQ_RETVAL( tid, 0 );     /* return value is meaningless */
@@ -1215,6 +1220,11 @@
          SET_CLREQ_RETVAL( tid, 0 );     /* return value is meaningless */
          break; }
 
+      case VG_USERREQ__STACK_SWITCH: {
+         VG_(switch_stack)((Addr)arg[1], (Addr)arg[2]);
+         SET_CLREQ_RETVAL( tid, 0 );     /* return value is meaningless */
+         break; }
+
       case VG_USERREQ__GET_MALLOCFUNCS: {
 	 struct vg_mallocfunc_info *info = (struct vg_mallocfunc_info *)arg[1];
 
diff -Nur valgrind-3.2.3/coregrind/m_sigframe/sigframe-x86-linux.c valgrind-3.2.3.new/coregrind/m_sigframe/sigframe-x86-linux.c
--- valgrind-3.2.3/coregrind/m_sigframe/sigframe-x86-linux.c	2007-01-07 23:43:11.000000000 -0800
+++ valgrind-3.2.3.new/coregrind/m_sigframe/sigframe-x86-linux.c	2007-11-05 12:56:23.000000000 -0800
@@ -405,6 +405,7 @@
    }
 
    if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
+      VG_(am_show_nsegments)(2, "Can't extend stack");
       VG_(message)(
          Vg_UserMsg,
          "Can't extend stack to %p during signal delivery for thread %d:",
@@ -414,6 +415,7 @@
       else
          VG_(message)(Vg_UserMsg, "  too small or bad protection modes");
 
+
       /* set SIGSEGV to default handler */
       VG_(set_default_handler)(VKI_SIGSEGV);
       VG_(synth_fault_mapping)(tid, addr);
diff -Nur valgrind-3.2.3/coregrind/m_stacks.c valgrind-3.2.3.new/coregrind/m_stacks.c
--- valgrind-3.2.3/coregrind/m_stacks.c	2007-01-07 23:43:15.000000000 -0800
+++ valgrind-3.2.3.new/coregrind/m_stacks.c	2007-12-01 08:38:20.000000000 -0800
@@ -126,6 +126,13 @@
       start = t;
    }
 
+   {
+      Stack *const j = find_stack_by_addr(start);
+      if (j && j->start==start && j->end==end) {
+         return j->id;
+      }
+   }
+
    i = (Stack *)VG_(arena_malloc)(VG_AR_CORE, sizeof(Stack));
    i->start = start;
    i->end = end;
@@ -154,7 +161,7 @@
 
    VG_(debugLog)(2, "stacks", "deregister stack %lu\n", id);
 
-   if (current_stack->id == id) {
+   if (current_stack && current_stack->id == id) {
       current_stack = NULL;
    }
 
@@ -171,6 +178,14 @@
       prev = i;
       i = i->next;
    }
+
+}
+void VG_(deregaddr_stack)(Addr addr)  /* from VALGRIND_STACK_DEREGADDR */
+{
+   Stack *j = find_stack_by_addr(addr);
+   if (j) {
+      VG_(deregister_stack)(j->id);
+   }
 }
 
 /*
@@ -195,6 +210,20 @@
    }
 }
 
+/* Switch stacks (longjmp, setcontext, etc., if modified to tell us.) */
+void VG_(switch_stack)(Addr old_SP, Addr new_SP)
+{
+   Stack* const old_stack = find_stack_by_addr(old_SP);
+   Stack* const new_stack = find_stack_by_addr(new_SP);
+
+   VG_(debugLog)(2, "stacks", "switch_stack 0x%lx ==> 0x%lx  (0x%lx)\n",
+      old_SP, new_SP, new_SP - old_SP);
+   if (NULL==new_stack) {
+      VG_(debugLog)(2, "stacks", "*** unknown stack above\n", 0);
+   }
+   current_stack = new_stack;
+}
+
 /* This function gets called if new_mem_stack and/or die_mem_stack are
    tracked by the tool, and one of the specialised cases
    (eg. new_mem_stack_4) isn't used in preference.  
@@ -205,15 +234,23 @@
    static Int moans = 3;
    Word delta  = (Word)new_SP - (Word)old_SP;
 
+   VG_(debugLog)(2, "stacks", "unknown_SP_update  old=0x%lx  new=0x%lx\n",
+      old_SP, new_SP);
    /* Check if the stack pointer is still in the same stack as before. */
    if (current_stack == NULL ||
        new_SP < current_stack->start || new_SP > current_stack->end) {
-      Stack* new_stack = find_stack_by_addr(new_SP);
+      Stack* const new_stack = find_stack_by_addr(new_SP);
       if (new_stack && new_stack->id != current_stack->id) {
-         /* The stack pointer is now in another stack.  Update the current
-            stack information and return without doing anything else. */
+         /* Remember the new stack. */
          current_stack = new_stack;
-         return;
+         if (old_SP < new_stack->start || old_SP > new_stack->end) {
+            /* The previous stack pointer is not in the new stack.
+               The user switched stacks, and we caught them in the act.
+               Do nothing. */
+            return;
+         }
+         /* Both old_SP and new_SP are in the new stack,
+            so continue processing ... */
       }
    }
 
diff -Nur valgrind-3.2.3/coregrind/pub_core_stacks.h valgrind-3.2.3.new/coregrind/pub_core_stacks.h
--- valgrind-3.2.3/coregrind/pub_core_stacks.h	2007-01-07 23:43:14.000000000 -0800
+++ valgrind-3.2.3.new/coregrind/pub_core_stacks.h	2007-11-08 09:28:16.000000000 -0800
@@ -38,7 +38,9 @@
 
 extern UWord VG_(register_stack)   ( Addr start, Addr end );
 extern void  VG_(deregister_stack) ( UWord id );
+extern void  VG_(deregaddr_stack) ( Addr addr );
 extern void  VG_(change_stack)     ( UWord id, Addr start, Addr end );
+extern void  VG_(switch_stack)     ( Addr old_sp, Addr new_sp );
 
 extern VG_REGPARM(2)
        void  VG_(unknown_SP_update) ( Addr old_SP, Addr new_SP );
diff -Nur valgrind-3.2.3/include/valgrind.h valgrind-3.2.3.new/include/valgrind.h
--- valgrind-3.2.3/include/valgrind.h	2007-01-07 23:43:09.000000000 -0800
+++ valgrind-3.2.3.new/include/valgrind.h	2007-11-08 09:35:52.000000000 -0800
@@ -2296,7 +2296,9 @@
           /* Stack support. */
           VG_USERREQ__STACK_REGISTER   = 0x1501,
           VG_USERREQ__STACK_DEREGISTER = 0x1502,
-          VG_USERREQ__STACK_CHANGE     = 0x1503
+          VG_USERREQ__STACK_CHANGE     = 0x1503,
+          VG_USERREQ__STACK_SWITCH     = 0x1504,
+          VG_USERREQ__STACK_DEREGADDR  = 0x1505
    } Vg_ClientRequest;
 
 #if !defined(__GNUC__)
@@ -2522,6 +2524,13 @@
                                id, 0, 0, 0, 0);                   \
    }
 
+#define VALGRIND_STACK_DEREGADDR(addr)                            \
+   {unsigned int _qzz_res;                                        \
+    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
+                               VG_USERREQ__STACK_DEREGADDR,       \
+                               addr, 0, 0, 0, 0);                 \
+   }
+
 /* Change the start and end address of the stack id. */
 #define VALGRIND_STACK_CHANGE(id, start, end)                     \
    {unsigned int _qzz_res;                                        \
@@ -2530,6 +2539,14 @@
                                id, start, end, 0, 0);             \
    }
 
+/* Notify that stack has changed. (For longjmp.) */
+#define VALGRIND_STACK_SWITCH(old_esp, new_esp)                   \
+   {unsigned int _qzz_res;                                        \
+    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                       \
+                               VG_USERREQ__STACK_SWITCH,          \
+                               old_esp, new_esp, 0, 0, 0);        \
+   }
+
 
 #undef ARCH_x86
 #undef ARCH_amd64
diff -Nur valgrind-3.2.3/longjmp.S valgrind-3.2.3.new/longjmp.S
--- valgrind-3.2.3/longjmp.S	1969-12-31 16:00:00.000000000 -0800
+++ valgrind-3.2.3.new/longjmp.S	2007-11-06 18:15:15.000000000 -0800
@@ -0,0 +1,37 @@
+/* longjmp(&jmpbuf, retval) hints stack switch to valgrind on i386.
+ * Copyright 2007 BitWagon Software LLC.  All rights reserved.
+ * Licensed under GNU General Public License, version 2.
+ * 2007-11-06  John Reiser
+ */
+
+VG_USERREQ__STACK_SWITCH = 0x1504  # valgrind/valgrind.h
+
+	.globl longjmp
+longjmp:
+	movl %esp,%ecx
+	movl 1*4(%ecx),%edx  # jmpbuf
+	movl 2*4(%ecx),%eax  # retval
+
+	movl    (%edx),%ebx
+	movl 1*4(%edx),%esp  # change stack now
+	movl 2*4(%edx),%ebp
+	movl 3*4(%edx),%esi
+	movl 4*4(%edx),%edi
+
+	movl 5*4(%edx),%edx; push %edx  # destination
+	push %eax  # retval
+
+	lea 2*4(%esp),%edx; push %edx  # new_sp
+	push %ecx  # old_sp
+	push $VG_USERREQ__STACK_SWITCH  # request
+	movl %esp,%eax  # &vector
+
+	roll $3,  %edi ; roll $13, %edi  # magic for VEX translator
+	roll $29, %edi ; roll $19, %edi
+	xchgl %ebx,%ebx
+
+	addl $3*4,%esp  # remove vector
+	pop %eax  # retval
+	ret  # goto destination
+
+	.section	.note.GNU-stack,"",@progbits  # stack not writable
-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell.  From the desktop to the data center, Linux is going
mainstream.  Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
_______________________________________________
Valgrind-developers mailing list
Valgrind-developers@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/valgrind-developers

Reply via email to