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/coregrind/vg_include.h b/coregrind/vg_include.h
index 206c6d8..f6cc1a5 100644
--- a/coregrind/vg_include.h
+++ b/coregrind/vg_include.h
@@ -353,6 +353,16 @@
void (*post_mem_write) ( Addr a, UInt size );
+ /* Register events */
+ void (*post_regs_write_init) ( void );
+ void (*post_reg_write_syscall_return) ( ThreadId tid, UInt reg );
+ void (*post_reg_write_deliver_signal) ( ThreadId tid, UInt reg );
+ void (*post_reg_write_pthread_return) ( ThreadId tid, UInt reg );
+ void (*post_reg_write_clientreq_return) ( ThreadId tid, UInt reg );
+ void (*post_reg_write_clientcall_return) ( ThreadId tid, UInt reg,
+ Addr f );
+
+
/* Scheduler events (not exhaustive) */
void (*thread_run) ( ThreadId tid );
@@ -923,24 +933,38 @@
(VG_AR_CLIENT_STACKBASE_REDZONE_SZW * VKI_BYTES_PER_WORD)
/* Junk to fill up a thread's shadow regs with when shadow regs aren't
- * being used. */
+ being used. */
#define VG_UNUSED_SHADOW_REG_VALUE 0x27182818
+/* For sanity checking: if this ends up in a thread's shadow regs when
+ shadow regs aren't being used, something went wrong. */
+#define VG_USED_SHADOW_REG_VALUE 0x31415927
-/* What we set a shadow register to when written by SET_EAX and similar
- * things. */
-extern UInt VG_(written_shadow_reg);
-
-/* Write a value to the client's %EDX (request return value register)
- and set the shadow to indicate it is defined. */
-#define SET_EDX(zztid, zzval) \
- do { VG_(threads)[zztid].m_edx = (zzval); \
- VG_(threads)[zztid].sh_edx = VG_(written_shadow_reg); \
+/* Write a value to a client's thread register, and shadow (if necessary) */
+#define SET_THREAD_REG( zztid, zzval, zzreg, zzREG, zzevent, zzargs... ) \
+ do { VG_(threads)[zztid].m_##zzreg = (zzval); \
+ VG_TRACK( zzevent, zztid, R_##zzREG, ##zzargs ); \
} while (0)
-#define SET_EAX(zztid, zzval) \
- do { VG_(threads)[zztid].m_eax = (zzval); \
- VG_(threads)[zztid].sh_eax = VG_(written_shadow_reg); \
- } while (0)
+#define SET_SYSCALL_RETVAL(zztid, zzval) \
+ SET_THREAD_REG(zztid, zzval, eax, EAX, post_reg_write_syscall_return)
+
+#define SET_SIGNAL_EDX(zztid, zzval) \
+ SET_THREAD_REG(zztid, zzval, edx, EDX, post_reg_write_deliver_signal)
+
+#define SET_SIGNAL_ESP(zztid, zzval) \
+ SET_THREAD_REG(zztid, zzval, esp, ESP, post_reg_write_deliver_signal)
+
+#define SET_CLREQ_RETVAL(zztid, zzval) \
+ SET_THREAD_REG(zztid, zzval, edx, EDX, post_reg_write_clientreq_return)
+
+#define SET_CLCALL_RETVAL(zztid, zzval, f) \
+ SET_THREAD_REG(zztid, zzval, edx, EDX, post_reg_write_clientcall_return, f)
+
+#define SET_PTHREQ_ESP(zztid, zzval) \
+ SET_THREAD_REG(zztid, zzval, esp, ESP, post_reg_write_pthread_return)
+
+#define SET_PTHREQ_RETVAL(zztid, zzval) \
+ SET_THREAD_REG(zztid, zzval, edx, EDX, post_reg_write_pthread_return)
/* This is or'd into a pthread mutex's __m_kind field if it is used
@@ -1435,14 +1459,14 @@
extern Bool VG_(is_kerror) ( Int res );
-#define KERNEL_DO_SYSCALL(thread_id, result_lvalue) \
- VG_(load_thread_state)(thread_id); \
- VG_(copy_baseBlock_to_m_state_static)(); \
- VG_(do_syscall)(); \
- VG_(copy_m_state_static_to_baseBlock)(); \
- VG_(save_thread_state)(thread_id); \
- VG_(threads)[thread_id].sh_eax = VG_(written_shadow_reg);\
- result_lvalue = VG_(threads)[thread_id].m_eax;
+#define KERNEL_DO_SYSCALL(thread_id, result_lvalue) \
+ VG_(load_thread_state)(thread_id); \
+ VG_(copy_baseBlock_to_m_state_static)(); \
+ VG_(do_syscall)(); \
+ VG_(copy_m_state_static_to_baseBlock)(); \
+ VG_(save_thread_state)(thread_id); \
+ result_lvalue = VG_(threads)[thread_id].m_eax; \
+ VG_TRACK( post_reg_write_syscall_return, thread_id, R_EAX );
/* ---------------------------------------------------------------------