Index: valgrind-quilt/coregrind/ppc-linux/core_platform.h =================================================================== --- valgrind-quilt.orig/coregrind/ppc-linux/core_platform.h 2005-06-15 13:42:29.790899296 -0400 +++ valgrind-quilt/coregrind/ppc-linux/core_platform.h 2005-06-15 14:11:39.462908416 -0400 @@ -75,20 +75,29 @@ #define PLATFORM_SYSCALL_GPR3(regs) ((regs).m_gpr[3]) #define PLATFORM_SYSCALL_CR(regs) ((regs).m_cr) -#define SET_SYSCALL_RETVAL(zztid, zzval) \ - do { \ - UInt __cr = VG_(threads)[zztid].arch.m_cr & ~0x10000000; \ - UInt __val = (zzval); \ - VG_(threads)[zztid].arch.m_result = __val; \ - if (__val > -4096) { \ - __val = - __val; \ - __cr |= 0x10000000; \ - } \ - SET_THREAD_REG(zztid, __val, PLATFORM_SYSCALL_GPR3, 3, \ - post_reg_write_syscall_return); \ - /* XXX this isn't right because it makes the whole CR valid. */ \ - SET_THREAD_REG(zztid, __cr, PLATFORM_SYSCALL_CR, R_CR, \ - post_reg_write_syscall_return); \ +/* Note: we do not modify the gpr3 for the sigreturn syscall. It's possible + * that sigreturn is returning from a signal which interrupted another system + * call, in which case we need to preserve the contents of gpr3 (which will + * either be the first argument for the interrupted system call if it's getting + * restarted, or EINTR if it's not). */ +#define SET_SYSCALL_RETVAL(zztid, zzval) \ + do { \ + int __syscallno = VG_(threads)[zztid].syscallno; \ + if ((__syscallno != __NR_sigreturn) && \ + (__syscallno != __NR_rt_sigreturn)) { \ + UInt __cr = VG_(threads)[zztid].arch.m_cr & ~0x10000000; \ + UInt __val = (zzval); \ + VG_(threads)[zztid].arch.m_result = __val; \ + if (__val > -4096) { \ + __val = - __val; \ + __cr |= 0x10000000; \ + } \ + SET_THREAD_REG(zztid, __val, PLATFORM_SYSCALL_GPR3, 3, \ + post_reg_write_syscall_return); \ + /* XXX this isn't right because it makes the whole CR valid. */ \ + SET_THREAD_REG(zztid, __cr, PLATFORM_SYSCALL_CR, R_CR, \ + post_reg_write_syscall_return); \ + } \ } while (0) /* --------------------------------------------------------------------- Index: valgrind-quilt/coregrind/vg_signals.c =================================================================== --- valgrind-quilt.orig/coregrind/vg_signals.c 2005-06-15 13:42:29.790899296 -0400 +++ valgrind-quilt/coregrind/vg_signals.c 2005-06-15 14:51:33.922895432 -0400 @@ -712,7 +712,16 @@ vg_assert(VG_(is_valid_tid)(tid)); do_setmask ( tid, how, set, oldset ); SET_SYSCALL_RETVAL(tid, 0); +#ifndef __powerpc__ + /* On PPC, gpr3 is used to hold both the first argument to a function and + * the syscall return value. If we poll for signals here and find one, + * we will put the first arg (sigNo) into gpr3. But later, before the + * signal handler gets run, we overwrite that with the sys_sigprocmask + * return value. So on PPC, we can't poll for signals here; we wait + * until POST(sys_sigprocmask) instead. */ + VG_(poll_signals)(tid); /* look for any newly deliverable signals */ +#endif break; default: Index: valgrind-quilt/coregrind/vg_syscalls.c =================================================================== --- valgrind-quilt.orig/coregrind/vg_syscalls.c 2005-06-15 14:24:27.238951672 -0400 +++ valgrind-quilt/coregrind/vg_syscalls.c 2005-06-15 14:23:08.752900296 -0400 @@ -5768,6 +5768,11 @@ POST(sys_sigprocmask) { +#ifdef __powerpc__ + /* PPC must delay the poll_signals call until now due to gpr3 sharing. See + * comment in VG_(do_sys_sigprocmask) for details. */ + VG_(poll_signals)(tid); +#endif if (SYSRES == 0 && arg3 != 0) POST_MEM_WRITE( arg3, sizeof(vki_old_sigset_t)); } @@ -5795,6 +5800,11 @@ POST(sys_rt_sigprocmask) { +#ifdef __powerpc__ + /* PPC must delay the poll_signals call until now due to gpr3 sharing. See + * comment in VG_(do_sys_sigprocmask) for details. */ + VG_(poll_signals)(tid); +#endif if (SYSRES == 0 && arg3 != 0) POST_MEM_WRITE( arg3, sizeof(vki_sigset_t)); }