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