This commit fixes up the handling of shadow registers quite a bit.

Removed the SK_(written_shadow_regs_values)() function.  Instead, skins that
use shadow regs can track the `post_regs_write_init' event, and set the shadow
regs from within it.  This is much more flexible, since it allows each shadow
register to be set to a separate value if necessary.  It also matches the new
shadow-reg-change events described below.

In the core, there were some places where the shadow regs were changed, and
skins had no way of knowing about it, which was a problem for some skins.
So I added a bunch of new events to notify skins about these:

  post_reg_write_syscall_return
  post_reg_write_deliver_signal
  post_reg_write_pthread_return
  post_reg_write_clientreq_return
  post_reg_write_clientcall_return

Any skin that uses shadow regs should almost certainly track these events.  The
post_reg_write_clientcall_return allows a skin to tailor the shadow reg of the
return value of a CLIENTCALL'd function appropriately;  this is especially
useful when replacing malloc() et al.

Defined some macros that should be used *whenever the core changes the value of
a shadow register* :

  SET_SYSCALL_RETVAL
  SET_SIGNAL_EDX          (maybe should be SET_SIGNAL_RETVAL? ... not sure)
  SET_SIGNAL_ESP
  SET_CLREQ_RETVAL
  SET_CLCALL_RETVAL
  SET_PTHREQ_ESP
  SET_PTHREQ_RETVAL

These replace all the old SET_EAX and SET_EDX macros, and are added in a few
places where the shadow-reg update was missing.

Added shadow registers to the machine state saved/restored when signal handlers
are pushed/popped (they were missing).

Added skin-callable functions VG_(set_return_from_syscall_shadow)() and
VG_(get_exit_status_shadow)() which are useful and abstract away from which
registers the results are in.

Also, poll() changes %ebx (it's first argument) sometimes, I don't know why.
So we notify skins about that too (with the `post_reg_write_syscall_return'
event, which isn't ideal I guess...)


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1642 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/include/vg_skin.h b/include/vg_skin.h
index 8a1ee91..6dd05cc 100644
--- a/include/vg_skin.h
+++ b/include/vg_skin.h
@@ -987,6 +987,7 @@
 
 extern UInt VG_(get_shadow_archreg)     ( UInt archreg );
 extern void VG_(set_shadow_archreg)     ( UInt archreg, UInt val );
+extern void VG_(set_shadow_eflags)      ( UInt val );
 extern Addr VG_(shadow_archreg_address) ( UInt archreg );
 
 extern UInt VG_(get_thread_shadow_archreg) ( ThreadId tid, UInt archreg );
@@ -1207,7 +1208,8 @@
 extern ExeContext* VG_(get_ExeContext) ( ThreadState *tst );
 
 /* Just grab the client's EIP, as a much smaller and cheaper
-   indication of where they are. */
+   indication of where they are.  ThreadState should be NULL if it's called
+   from within generated code. */
 extern Addr VG_(get_EIP)( ThreadState *tst );
 
 
@@ -1470,6 +1472,23 @@
 
 
 /*====================================================================*/
+/*=== Functions for shadow registers                               ===*/
+/*====================================================================*/
+
+/* Nb: make sure the shadow_regs 'need' is set before using these! */
+
+/* This one lets you override the shadow of the return value register for a
+   syscall.  Call it from SK_(post_syscall)() (not SK_(pre_syscall)()!) to
+   override the default shadow register value. */
+extern void VG_(set_return_from_syscall_shadow) ( ThreadId tid, 
+                                                  UInt ret_shadow );
+
+/* This can be called from SK_(fini)() to find the shadow of the argument
+   to exit(), ie. the shadow of the program's return value. */
+extern UInt VG_(get_exit_status_shadow) ( void );
+
+
+/*====================================================================*/
 /*=== General stuff for replacing functions                        ===*/
 /*====================================================================*/
 
@@ -1499,9 +1518,6 @@
 /*=== Specific stuff for replacing malloc() and friends            ===*/
 /*====================================================================*/
 
-/* ------------------------------------------------------------------ */
-/* Replacing malloc() and friends */
-
 /* If a skin replaces malloc() et al, the easiest way to do so is to link
    with coregrind/vg_replace_malloc.c, and follow the following instructions.
    You can do it from scratch, though, if you enjoy that sort of thing. */
@@ -1536,8 +1552,8 @@
 
 /* ------------------------------------------------------------------ */
 /* Some options that can be used by a skin if malloc() et al are replaced. 
-   The skin should use the VG_(process...)() and VG_(print...)() functions
-   to give control over these aspects of Valgrind's version of malloc(). */
+   The skin should call the functions in the appropriate places to give
+   control over these aspects of Valgrind's version of malloc(). */
 
 /* Round malloc sizes upwards to integral number of words? default: NO */
 extern Bool VG_(clo_sloppy_malloc);
@@ -1711,6 +1727,30 @@
 EV VG_(track_post_mem_write) ( void (*f)(Addr a, UInt size) );
 
 
+/* Register events -- if `shadow_regs' need is set, all should probably be
+   used.  Use VG_(set_thread_shadow_archreg)() to set the shadow of the
+   changed register. */
+
+/* Use VG_(set_shadow_archreg)() to set the eight general purpose regs,
+   and use VG_(set_shadow_eflags)() to set eflags. */
+EV VG_(track_post_regs_write_init)  ( void (*f)() );    
+
+/* Use VG_(set_thread_shadow_archreg)() to set the shadow regs for these 
+   events. */
+EV VG_(track_post_reg_write_syscall_return)    
+                                    ( void (*f)(ThreadId tid, UInt reg) );
+EV VG_(track_post_reg_write_deliver_signal)
+                                    ( void (*f)(ThreadId tid, UInt reg) );
+EV VG_(track_post_reg_write_pthread_return)
+                                    ( void (*f)(ThreadId tid, UInt reg) );
+EV VG_(track_post_reg_write_clientreq_return)
+                                    ( void (*f)(ThreadId tid, UInt reg) );
+   /* This one is called for malloc() et al if they are replaced by a skin. */
+EV VG_(track_post_reg_write_clientcall_return)
+                                    ( void (*f)(ThreadId tid, UInt reg,
+                                                Addr called_function) );
+
+
 /* Scheduler events (not exhaustive) */
 
 EV VG_(track_thread_run) ( void (*f)(ThreadId tid) );
@@ -1865,10 +1905,8 @@
 /* ------------------------------------------------------------------ */
 /* VG_(needs).shadow_regs */
 
-/* Valid values for general registers and EFLAGS register, for initialising
-   and updating registers when written in certain places in core. */
-extern void SK_(written_shadow_regs_values) ( UInt* gen_reg, UInt* eflags );
-
+/* No functions must be defined, but the post_reg[s]_write_* events should
+   be tracked. */
 
 /* ------------------------------------------------------------------ */
 /* VG_(needs).command_line_options */
@@ -1886,7 +1924,19 @@
 /* ------------------------------------------------------------------ */
 /* VG_(needs).client_requests */
 
-extern Bool SK_(handle_client_request) ( ThreadState* tst, UInt* arg_block, UInt *ret );
+/* If using client requests, the number of the first request should be equal
+   to VG_USERREQ_SKIN_BASE('X','Y'), where 'X' and 'Y' form a suitable two
+   character identification for the string.  The second and subsequent
+   requests should follow. */
+
+/* This function should use the VG_IS_SKIN_USERREQ macro (in
+   include/valgrind.h) to first check if it's a request for this skin.  Then
+   should handle it if it's recognised (and return True), or return False if
+   not recognised.  arg_block[0] holds the request number, any further args
+   from the request are in arg_block[1..].  'ret' is for the return value...
+   it should probably be filled, if only with 0. */
+extern Bool SK_(handle_client_request) ( ThreadState* tst, UInt* arg_block,
+                                         UInt *ret );
 
 
 /* ------------------------------------------------------------------ */