Use sigreturn/rt_sigreturn to finish a signal handler rather than using a client request. This allows clients to use SA_RESTORER, and it helps gdb understand the signal stack frames Valgrind generates. coregrind/core.h | 8 coregrind/vg_scheduler.c | 9 coregrind/vg_signals.c | 26 -- coregrind/x86-linux/syscalls.c | 34 ++- coregrind/x86/core_arch.h | 5 coregrind/x86/helpers.S | 33 +- coregrind/x86/signal.c | 456 ++++++++++++++++++++++++----------------- 7 files changed, 333 insertions(+), 238 deletions(-) diff -puN coregrind/x86/helpers.S~sigreturn-syscall coregrind/x86/helpers.S --- valgrind/coregrind/x86/helpers.S~sigreturn-syscall 2005-01-12 18:43:21.000000000 -0800 +++ valgrind-jeremy/coregrind/x86/helpers.S 2005-01-12 18:43:21.000000000 -0800 @@ -28,6 +28,7 @@ */ #include "core_asm.h" +#include "vki_unistd.h" /* ------------------ SIMULATED CPU HELPERS ------------------ */ /* A stubs for a return which we want to catch: a signal return. @@ -44,26 +45,22 @@ .global VG_(trampoline_code_start) .global VG_(trampoline_code_length) .global VG_(tramp_sigreturn_offset) +.global VG_(tramp_rt_sigreturn_offset) .global VG_(tramp_syscall_offset) VG_(trampoline_code_start): -sigreturn_start: - subl $20, %esp # allocate arg block - movl %esp, %edx # %edx == &_zzq_args[0] - movl $VG_USERREQ__SIGNAL_RETURNS, 0(%edx) # request - movl $0, 4(%edx) # arg1 - movl $0, 8(%edx) # arg2 - movl $0, 12(%edx) # arg3 - movl $0, 16(%edx) # arg4 - movl %edx, %eax - # and now the magic sequence itself: - roll $29, %eax - roll $3, %eax - rorl $27, %eax - rorl $5, %eax - roll $13, %eax - roll $19, %eax - # should never get here +sigreturn_start: + /* This is a very specific sequence which GDB uses to + recognize signal handler frames. */ + popl %eax + movl $__NR_sigreturn, %eax + int $0x80 + ud2 + +rt_sigreturn_start: + /* Likewise for rt signal frames */ + movl $__NR_rt_sigreturn, %eax + int $0x80 ud2 # We can point our sysinfo stuff here @@ -78,6 +75,8 @@ VG_(trampoline_code_length): .long tramp_code_end - VG_(trampoline_code_start) VG_(tramp_sigreturn_offset): .long sigreturn_start - VG_(trampoline_code_start) +VG_(tramp_rt_sigreturn_offset): + .long rt_sigreturn_start - VG_(trampoline_code_start) VG_(tramp_syscall_offset): .long syscall_start - VG_(trampoline_code_start) .text diff -puN coregrind/core.h~sigreturn-syscall coregrind/core.h --- valgrind/coregrind/core.h~sigreturn-syscall 2005-01-12 18:43:21.000000000 -0800 +++ valgrind-jeremy/coregrind/core.h 2005-01-12 18:43:21.000000000 -0800 @@ -868,9 +868,6 @@ extern void VG_(do_pthread_sigmask_SCSS_ vki_sigset_t* set, vki_sigset_t* oldset ); -/* Restore thread's state on return from a signal handler */ -extern void VG_(signal_returns) ( ThreadId tid ); - /* Handy utilities to block/restore all host signals. */ extern void VG_(block_all_host_signals) ( /* OUT */ vki_sigset_t* saved_mask ); @@ -1666,6 +1663,7 @@ extern void VG_(helper_undefined_instruc extern const Char VG_(trampoline_code_start); extern const Int VG_(trampoline_code_length); extern const Int VG_(tramp_sigreturn_offset); +extern const Int VG_(tramp_rt_sigreturn_offset); extern const Int VG_(tramp_syscall_offset); /* --------------------------------------------------------------------- @@ -1763,8 +1761,8 @@ extern void VGA_(fill_elffpxregs_from_ts extern void VGA_(push_signal_frame) ( ThreadId tid, Addr sp_top_of_frame, const vki_siginfo_t *siginfo, void *handler, UInt flags, - const vki_sigset_t *mask); -extern Int VGA_(pop_signal_frame) ( ThreadId tid ); + const vki_sigset_t *mask, + void *restorer ); #define MY__STRING(__str) #__str diff -puN coregrind/x86/signal.c~sigreturn-syscall coregrind/x86/signal.c --- valgrind/coregrind/x86/signal.c~sigreturn-syscall 2005-01-12 18:43:21.000000000 -0800 +++ valgrind-jeremy/coregrind/x86/signal.c 2005-01-12 18:43:21.000000000 -0800 @@ -37,73 +37,80 @@ // A structure in which to save the application's registers // during the execution of signal handlers. -typedef - struct { - /* There are two different stack frame formats, depending on - whether the client set the SA_SIGINFO flag for the handler. - This structure is put onto the client's stack as part of - signal delivery, and therefore appears as the signal - handler's arguments. - - The first two words are common for both frame formats - - they're the return address and the signal number. */ - - /* Sig handler's return address */ - Addr retaddr; - /* The arg to the sig handler. We need to inspect this after - the handler returns, but it's unreasonable to assume that the - handler won't change it. So we keep a second copy of it in - sigNo_private. */ - Int sigNo; - - /* This is where the two frames start differing. */ - union { - struct { /* set SA_SIGINFO */ - /* ptr to siginfo_t. */ - Addr psigInfo; - - /* ptr to ucontext */ - Addr puContext; - } sigInfo; - struct vki_sigcontext sigContext; /* did not set SA_SIGINFO */ - } handlerArgs; - - /* The rest are private fields which the handler is unaware of. */ - - /* Sanity check word. */ - UInt magicPI; - - UInt handlerflags; /* flags for signal handler */ - - /* pointed to by psigInfo */ - vki_siginfo_t sigInfo; - /* pointed to by puContext */ - struct vki_ucontext uContext; - struct _vki_fpstate fpstate; - - /* Safely-saved version of sigNo, as described above. */ - Int sigNo_private; - - /* XXX This is wrong. Surely we should store the shadow values - into the shadow memory behind the actual values? */ - UInt sh_eax; - UInt sh_ebx; - UInt sh_ecx; - UInt sh_edx; - UInt sh_esi; - UInt sh_edi; - UInt sh_ebp; - UInt sh_esp; - UInt sh_eflags; - - /* saved signal mask to be restored when handler returns */ - vki_sigset_t mask; - - /* Sanity check word. Is the highest-addressed word; do not - move!*/ - UInt magicE; - } - VgSigFrame; +// Linux has 2 signal frame structures: one for normal signal +// deliveries, and one for SA_SIGINFO deliveries (also known as RT +// signals). +// +// In theory, so long as we get the arguments to the handler function +// right, it doesn't matter what the exact layout of the rest of the +// frame is. Unfortunately, things like gcc's exception unwinding +// make assumptions about the locations of various parts of the frame, +// so we need to duplicate it exactly. + +/* Valgrind-specific parts of the signal frame */ +struct vg_sigframe +{ + /* Sanity check word. */ + UInt magicPI; + + UInt handlerflags; /* flags for signal handler */ + + + /* Safely-saved version of sigNo, as described above. */ + Int sigNo_private; + + /* XXX This is wrong. Surely we should store the shadow values + into the shadow memory behind the actual values? */ + UInt sh_eax; + UInt sh_ebx; + UInt sh_ecx; + UInt sh_edx; + UInt sh_esi; + UInt sh_edi; + UInt sh_ebp; + UInt sh_esp; + UInt sh_eflags; + + /* saved signal mask to be restored when handler returns */ + vki_sigset_t mask; + + /* Sanity check word. Is the highest-addressed word; do not + move!*/ + UInt magicE; +}; + +struct sigframe +{ + /* Sig handler's return address */ + Addr retaddr; + Int sigNo; + + struct vki_sigcontext sigContext; + struct _vki_fpstate fpstate; + + struct vg_sigframe vg; +}; + +struct rt_sigframe +{ + /* Sig handler's return address */ + Addr retaddr; + Int sigNo; + + /* ptr to siginfo_t. */ + Addr psigInfo; + + /* ptr to ucontext */ + Addr puContext; + /* pointed to by psigInfo */ + vki_siginfo_t sigInfo; + + /* pointed to by puContext */ + struct vki_ucontext uContext; + struct _vki_fpstate fpstate; + + struct vg_sigframe vg; +}; /*------------------------------------------------------------*/ /*--- Signal operations ---*/ @@ -342,33 +349,23 @@ static void synth_ucontext(ThreadId tid, SET_THREAD_REG(zztid, zzval, ARCH_STACK_PTR, R_STACK_PTR, \ post_reg_write_deliver_signal) -void VGA_(push_signal_frame)(ThreadId tid, Addr esp_top_of_frame, - const vki_siginfo_t *siginfo, - void *handler, UInt flags, - const vki_sigset_t *mask) +static Bool extend(ThreadState *tst, Addr addr, SizeT size) { - Addr esp; - ThreadState* tst = VG_(get_ThreadState)(tid); - VgSigFrame* frame; - Int sigNo = siginfo->si_signo; - Segment *stackseg = NULL; - - esp = esp_top_of_frame; - esp -= sizeof(VgSigFrame); - frame = (VgSigFrame*)esp; + ThreadId tid = tst->tid; + Segment *stackseg = NULL; - if (VG_(extend_stack)((Addr)frame, tst->stack_size)) { - stackseg = VG_(find_segment)((Addr)frame); + if (VG_(extend_stack)(addr, tst->stack_size)) { + stackseg = VG_(find_segment)(addr); if (0 && stackseg) VG_(printf)("frame=%p seg=%p-%p\n", - frame, stackseg->addr, stackseg->addr+stackseg->len); + addr, stackseg->addr, stackseg->addr+stackseg->len); } if (stackseg == NULL || - !VG_(is_addressable)((Addr)frame, sizeof(*frame), VKI_PROT_READ|VKI_PROT_WRITE)) { + !VG_(is_addressable)(addr, size, VKI_PROT_READ|VKI_PROT_WRITE)) { VG_(message)(Vg_UserMsg, "Can't extend stack to %p during signal delivery for thread %d:", - frame, tid); + addr, tid); if (stackseg == NULL) VG_(message)(Vg_UserMsg, " no stack segment"); else @@ -376,68 +373,27 @@ void VGA_(push_signal_frame)(ThreadId ti /* set SIGSEGV to default handler */ VG_(set_default_handler)(VKI_SIGSEGV); - VG_(synth_fault_mapping)(tid, (Addr)frame); + VG_(synth_fault_mapping)(tid, addr); /* The whole process should be about to die, since the default action of SIGSEGV to kill the whole process. */ - return; + return False; } /* For tracking memory events, indicate the entire frame has been - * allocated, but pretend that only the first four words are written */ - VG_TRACK( new_mem_stack_signal, (Addr)frame, sizeof(VgSigFrame) ); - - /* Assert that the frame is placed correctly. */ - vg_assert( (sizeof(VgSigFrame) & 0x3) == 0 ); - vg_assert( ((Char*)(&frame->magicE)) + sizeof(UInt) - == ((Char*)(esp_top_of_frame)) ); - - /* retaddr, sigNo, psigInfo, puContext fields are to be written */ - VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame", - (Addr)frame, offsetof(VgSigFrame, handlerArgs) ); - frame->retaddr = (UInt)VG_(client_trampoline_code)+VG_(tramp_sigreturn_offset); - frame->sigNo = sigNo; - frame->sigNo_private = sigNo; - - VG_TRACK( post_mem_write, (Addr)frame, offsetof(VgSigFrame, handlerArgs) ); - - if (flags & VKI_SA_SIGINFO) { - /* if the client asked for a siginfo delivery, then build the stack that way */ - - /* pointers to siginfo and ucontext */ - VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame (siginfo)", - (Addr)&frame->handlerArgs, sizeof(frame->handlerArgs.sigInfo) ); - frame->handlerArgs.sigInfo.psigInfo = (Addr)&frame->sigInfo; - frame->handlerArgs.sigInfo.puContext = (Addr)&frame->uContext; - VG_TRACK( post_mem_write, (Addr)&frame->handlerArgs, sizeof(frame->handlerArgs.sigInfo) ); - - /* siginfo */ - VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame (siginfo)", - (Addr)&frame->sigInfo, sizeof(frame->sigInfo) ); - VG_(memcpy)(&frame->sigInfo, siginfo, sizeof(vki_siginfo_t)); - VG_TRACK( post_mem_write, (Addr)&frame->sigInfo, sizeof(frame->sigInfo) ); - - /* ucontext */ - VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame (ucontext)", - (Addr)&frame->uContext, sizeof(frame->uContext) ); - synth_ucontext(tid, siginfo, mask, &frame->uContext, &frame->fpstate); - VG_TRACK( post_mem_write, (Addr)&frame->uContext, sizeof(frame->uContext) ); - } else { - struct vki_ucontext uc; + allocated. */ + VG_TRACK( new_mem_stack_signal, addr, size ); - /* non-siginfo: just put the sigcontext there */ - - synth_ucontext(tid, siginfo, mask, &uc, &frame->fpstate); + return True; +} - VG_TRACK( pre_mem_write, Vg_CoreSignal, tid, "signal handler frame (sigcontext)", - (Addr)&frame->handlerArgs, sizeof(frame->handlerArgs.sigContext) ); - VG_(memcpy)(&frame->handlerArgs.sigContext, &uc.uc_mcontext, - sizeof(struct vki_sigcontext)); - VG_TRACK( post_mem_write, (Addr)&frame->handlerArgs, - sizeof(frame->handlerArgs.sigContext) ); - - frame->handlerArgs.sigContext.oldmask = tst->sig_mask.sig[0]; - } +static void build_vg_sigframe(struct vg_sigframe *frame, + ThreadState *tst, + const vki_sigset_t *mask, + UInt flags, + Int sigNo) +{ + frame->sigNo_private = sigNo; frame->magicPI = 0x31415927; @@ -458,9 +414,114 @@ void VGA_(push_signal_frame)(ThreadId ti frame->handlerflags = flags; frame->magicE = 0x27182818; +} + +static Addr build_sigframe(ThreadState *tst, + Addr esp_top_of_frame, + const vki_siginfo_t *siginfo, + void *handler, UInt flags, + const vki_sigset_t *mask, + void *restorer) +{ + struct sigframe *frame; + Addr esp = esp_top_of_frame; + Int sigNo = siginfo->si_signo; + struct vki_ucontext uc; + + esp -= sizeof(*frame); + esp = ROUNDDN(esp, 16); + frame = (struct sigframe *)esp; + + if (!extend(tst, esp, sizeof(*frame))) + return esp_top_of_frame; + + /* retaddr, sigNo, siguContext fields are to be written */ + VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame", + esp, offsetof(struct sigframe, vg) ); + + frame->sigNo = sigNo; + + if (flags & VKI_SA_RESTORER) + frame->retaddr = (Addr)restorer; + else { + if (flags & VKI_SA_SIGINFO) + frame->retaddr = (UInt)VG_(client_trampoline_code)+VG_(tramp_rt_sigreturn_offset); + else + frame->retaddr = (UInt)VG_(client_trampoline_code)+VG_(tramp_sigreturn_offset); + } + + synth_ucontext(tst->tid, siginfo, mask, &uc, &frame->fpstate); + + VG_(memcpy)(&frame->sigContext, &uc.uc_mcontext, + sizeof(struct vki_sigcontext)); + frame->sigContext.oldmask = tst->sig_mask.sig[0]; + + VG_TRACK( post_mem_write, esp, offsetof(struct sigframe, vg) ); + + build_vg_sigframe(&frame->vg, tst, mask, flags, sigNo); + + return esp; +} + +static Addr build_rt_sigframe(ThreadState *tst, + Addr esp_top_of_frame, + const vki_siginfo_t *siginfo, + void *handler, UInt flags, + const vki_sigset_t *mask, + void *restorer) +{ + struct rt_sigframe *frame; + Addr esp = esp_top_of_frame; + Int sigNo = siginfo->si_signo; + + esp -= sizeof(*frame); + esp = ROUNDDN(esp, 16); + frame = (struct rt_sigframe *)esp; + + if (!extend(tst, esp, sizeof(*frame))) + return esp_top_of_frame; + + /* retaddr, sigNo, pSiginfo, puContext fields are to be written */ + VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "rt signal handler frame", + esp, offsetof(struct rt_sigframe, vg) ); + + frame->sigNo = sigNo; + + if (flags & VKI_SA_RESTORER) + frame->retaddr = (Addr)restorer; + else { + if (flags & VKI_SA_SIGINFO) + frame->retaddr = (UInt)VG_(client_trampoline_code)+VG_(tramp_rt_sigreturn_offset); + else + frame->retaddr = (UInt)VG_(client_trampoline_code)+VG_(tramp_sigreturn_offset); + } + + frame->psigInfo = (Addr)&frame->sigInfo; + frame->puContext = (Addr)&frame->uContext; + VG_(memcpy)(&frame->sigInfo, siginfo, sizeof(vki_siginfo_t)); + synth_ucontext(tst->tid, siginfo, mask, &frame->uContext, &frame->fpstate); + + VG_TRACK( post_mem_write, esp, offsetof(struct rt_sigframe, vg) ); + + build_vg_sigframe(&frame->vg, tst, mask, flags, sigNo); + + return esp; +} + +void VGA_(push_signal_frame)(ThreadId tid, Addr esp_top_of_frame, + const vki_siginfo_t *siginfo, + void *handler, UInt flags, + const vki_sigset_t *mask, + void *restorer) +{ + Addr esp; + ThreadState* tst = VG_(get_ThreadState)(tid); + + if (flags & VKI_SA_SIGINFO) + esp = build_rt_sigframe(tst, esp_top_of_frame, siginfo, handler, flags, mask, restorer); + else + esp = build_sigframe(tst, esp_top_of_frame, siginfo, handler, flags, mask, restorer); - /* Ensure 'tid' and 'tst' correspond */ - vg_assert(& VG_(threads)[tid] == tst); /* Set the thread so it will next run the handler. */ /* tst->m_esp = esp; */ SET_SIGNAL_ESP(tid, esp); @@ -475,34 +536,40 @@ void VGA_(push_signal_frame)(ThreadId ti esp, tst->arch.m_eip, tst->status); } -Int VGA_(pop_signal_frame)(ThreadId tid) +static Bool restore_vg_sigframe(ThreadState *tst, struct vg_sigframe *frame, Int *sigNo) { - Addr esp; - VgSigFrame* frame; - ThreadState* tst; - struct vki_sigcontext *sc; + if (frame->magicPI != 0x31415927 || + frame->magicE != 0x27182818) { + VG_(message)(Vg_UserMsg, "Thread %d return signal frame corrupted. Killing process.", + tst->tid); + VG_(set_default_handler)(VKI_SIGSEGV); + VG_(synth_fault)(tst->tid); + *sigNo = VKI_SIGSEGV; + return False; + } + + tst->sig_mask = frame->mask; + + if (VG_(needs).shadow_regs) { + tst->arch.sh_eax = frame->sh_eax; + tst->arch.sh_ecx = frame->sh_ecx; + tst->arch.sh_edx = frame->sh_edx; + tst->arch.sh_ebx = frame->sh_ebx; + tst->arch.sh_ebp = frame->sh_ebp; + tst->arch.sh_esp = frame->sh_esp; + tst->arch.sh_esi = frame->sh_esi; + tst->arch.sh_edi = frame->sh_edi; + tst->arch.sh_eflags = frame->sh_eflags; + } - vg_assert(VG_(is_valid_tid)(tid)); - tst = & VG_(threads)[tid]; + *sigNo = frame->sigNo_private; - /* Correctly reestablish the frame base address. */ - esp = tst->arch.m_esp; - frame = (VgSigFrame*) - (esp -4 /* because the handler's RET pops the RA */ - +20 /* because signalreturn_bogusRA pushes 5 words */); - - vg_assert(frame->magicPI == 0x31415927); - vg_assert(frame->magicE == 0x27182818); - - /* Mark the frame structure as nonaccessible. */ - VG_TRACK( die_mem_stack_signal, (Addr)frame, sizeof(VgSigFrame) ); - - /* restore machine state */ - if (frame->handlerflags & VKI_SA_SIGINFO) - sc = &frame->uContext.uc_mcontext; - else - sc = &frame->handlerArgs.sigContext; + return True; +} +static void restore_sigcontext(ThreadState *tst, struct vki_sigcontext *sc, + struct _vki_fpstate *fpstate) +{ tst->arch.m_eax = sc->eax; tst->arch.m_ecx = sc->ecx; tst->arch.m_edx = sc->edx; @@ -521,30 +588,51 @@ Int VGA_(pop_signal_frame)(ThreadId tid) tst->arch.m_fs = sc->fs; tst->arch.m_gs = sc->gs; - restore_i387(&tst->arch, &frame->fpstate); + restore_i387(&tst->arch, fpstate); +} - if (VG_(needs).shadow_regs) { - tst->arch.sh_eax = frame->sh_eax; - tst->arch.sh_ecx = frame->sh_ecx; - tst->arch.sh_edx = frame->sh_edx; - tst->arch.sh_ebx = frame->sh_ebx; - tst->arch.sh_ebp = frame->sh_ebp; - tst->arch.sh_esp = frame->sh_esp; - tst->arch.sh_esi = frame->sh_esi; - tst->arch.sh_edi = frame->sh_edi; - tst->arch.sh_eflags = frame->sh_eflags; - } +static SizeT restore_sigframe(ThreadState *tst, struct sigframe *frame, Int *sigNo) +{ + if (restore_vg_sigframe(tst, &frame->vg, sigNo)) + restore_sigcontext(tst, &frame->sigContext, &frame->fpstate); + + return sizeof(*frame); +} + +static SizeT restore_rt_sigframe(ThreadState *tst, struct rt_sigframe *frame, Int *sigNo) +{ + if (restore_vg_sigframe(tst, &frame->vg, sigNo)) + restore_sigcontext(tst, &frame->uContext.uc_mcontext, &frame->fpstate); + + return sizeof(*frame); +} + +void VGA_(signal_return)(ThreadId tid, Bool isRT) +{ + Addr esp; + ThreadState* tst; + SizeT size; + Int sigNo; + + tst = VG_(get_ThreadState)(tid); + + /* Correctly reestablish the frame base address. */ + esp = tst->arch.m_esp; + + if (!isRT) + size = restore_sigframe(tst, (struct sigframe *)esp, &sigNo); + else + size = restore_rt_sigframe(tst, (struct rt_sigframe *)esp, &sigNo); + + VG_TRACK( die_mem_stack_signal, esp, size ); if (VG_(clo_trace_signals)) VG_(message)(Vg_DebugMsg, - "vg_pop_signal_frame (thread %d): valid magic; EIP=%p", - tid, sc->eip); - - tst->sig_mask = frame->mask; + "vg_pop_signal_frame (thread %d): isRT=%d valid magic; EIP=%p", + tid, isRT, tst->arch.m_eip); - /* don't use the copy exposed to the handler; it might have changed - it. */ - return frame->sigNo_private; + /* tell the tools */ + VG_TRACK( post_deliver_signal, tid, sigNo ); } /*------------------------------------------------------------*/ diff -puN coregrind/x86-linux/syscalls.c~sigreturn-syscall coregrind/x86-linux/syscalls.c --- valgrind/coregrind/x86-linux/syscalls.c~sigreturn-syscall 2005-01-12 18:43:21.000000000 -0800 +++ valgrind-jeremy/coregrind/x86-linux/syscalls.c 2005-01-12 18:43:21.000000000 -0800 @@ -462,6 +462,36 @@ PRE(sys_clone, Special) } } +PRE(sys_sigreturn, Special) +{ + PRINT("sigreturn ( )"); + + /* Adjust esp to point to start of frame; skip back up over + sigreturn sequence's "popl %eax" and handler ret addr */ + tst->arch.m_esp -= sizeof(Addr)+sizeof(Word); + + /* This is only so that the EIP is (might be) useful to report if + something goes wrong in the sigreturn */ + restart_syscall(&tst->arch); + + VGA_(signal_return)(tid, False); +} + +PRE(sys_rt_sigreturn, Special) +{ + PRINT("rt_sigreturn ( )"); + + /* Adjust esp to point to start of frame; skip back up over handler + ret addr */ + tst->arch.m_esp -= sizeof(Addr); + + /* This is only so that the EIP is (might be) useful to report if + something goes wrong in the sigreturn */ + restart_syscall(&tst->arch); + + VGA_(signal_return)(tid, True); +} + PRE(sys_modify_ldt, Special) { PRINT("sys_modify_ldt ( %d, %p, %d )", arg1,arg2,arg3); @@ -697,7 +727,7 @@ const struct SyscallTableEntry VGA_(sysc LINXY(__NR_sysinfo, sys_sysinfo), // 116 GENXY(__NR_ipc, sys_ipc), // 117 GENX_(__NR_fsync, sys_fsync), // 118 - // (__NR_sigreturn, sys_sigreturn), // 119 ?/Linux + PLAX_(__NR_sigreturn, sys_sigreturn), // 119 ?/Linux PLAX_(__NR_clone, sys_clone), // 120 // (__NR_setdomainname, sys_setdomainname), // 121 */*(?) @@ -764,7 +794,7 @@ const struct SyscallTableEntry VGA_(sysc LINX_(__NR_setresgid, sys_setresgid16), // 170 LINXY(__NR_getresgid, sys_getresgid16), // 171 LINX_(__NR_prctl, sys_prctl), // 172 - // (__NR_rt_sigreturn, sys_rt_sigreturn), // 173 x86/Linux only? + PLAX_(__NR_rt_sigreturn, sys_rt_sigreturn), // 173 x86/Linux only? GENXY(__NR_rt_sigaction, sys_rt_sigaction), // 174 GENXY(__NR_rt_sigprocmask, sys_rt_sigprocmask), // 175 diff -puN coregrind/vg_scheduler.c~sigreturn-syscall coregrind/vg_scheduler.c --- valgrind/coregrind/vg_scheduler.c~sigreturn-syscall 2005-01-12 18:43:21.000000000 -0800 +++ valgrind-jeremy/coregrind/vg_scheduler.c 2005-01-12 18:43:21.000000000 -0800 @@ -535,8 +535,8 @@ UInt run_thread_for_a_while ( ThreadId t may already be up to date. */ if (VG_(is_VCPU_thread)(tid)) VG_(save_thread_state) ( tid ); - else - vg_assert(VG_(get_VCPU_tid)() == VG_INVALID_THREADID); + + vg_assert(VG_(get_VCPU_tid)() == VG_INVALID_THREADID); VGP_POPCC(VgpRun); return trc; @@ -982,10 +982,6 @@ void do_client_request ( ThreadId tid ) SET_PTHREQ_RETVAL(tid, VG_(read_millisecond_timer)()); break; - case VG_USERREQ__SIGNAL_RETURNS: - VG_(signal_returns)(tid); - break; - case VG_USERREQ__PRINTF: { int count = VG_(vmessage)( Vg_ClientMsg, (char *)arg[1], (void*)arg[2] ); @@ -1096,6 +1092,7 @@ void do_client_request ( ThreadId tid ) case VG_USERREQ__GET_SIGRT_MIN: case VG_USERREQ__GET_SIGRT_MAX: case VG_USERREQ__ALLOC_RTSIG: + case VG_USERREQ__SIGNAL_RETURNS: /* not pthreads, but obsolete */ VG_(message)(Vg_UserMsg, "It looks like you've got an old libpthread.so* "); VG_(message)(Vg_UserMsg, "installed in \"%s\".", VG_(libdir)); VG_(message)(Vg_UserMsg, "Please delete it and try again."); diff -puN coregrind/vg_signals.c~sigreturn-syscall coregrind/vg_signals.c --- valgrind/coregrind/vg_signals.c~sigreturn-syscall 2005-01-12 18:43:21.000000000 -0800 +++ valgrind-jeremy/coregrind/vg_signals.c 2005-01-12 18:43:21.000000000 -0800 @@ -748,32 +748,10 @@ void vg_push_signal_frame ( ThreadId tid VGA_(push_signal_frame)(tid, esp_top_of_frame, siginfo, vg_scss.scss_per_sig[sigNo].scss_handler, vg_scss.scss_per_sig[sigNo].scss_flags, - &vg_scss.scss_per_sig[sigNo].scss_mask); + &vg_scss.scss_per_sig[sigNo].scss_mask, + vg_scss.scss_per_sig[sigNo].scss_restorer); } -/* Clear the signal frame created by vg_push_signal_frame, restore the - simulated machine state. */ -static -void vg_pop_signal_frame ( ThreadId tid ) -{ - Int sigNo = VGA_(pop_signal_frame)(tid); - - /* Notify tools */ - VG_TRACK( post_deliver_signal, tid, sigNo ); -} - - -/* A handler is returning. Restore the machine state from the stacked - VgSigContext and continue with whatever was going on before the - handler ran. Returns the SA_RESTART syscall-restartability-status - of the delivered signal. */ - -void VG_(signal_returns) ( ThreadId tid ) -{ - /* Pop the signal frame and restore tid's status to what it was - before the signal was delivered. */ - vg_pop_signal_frame(tid); -} static const Char *signame(Int sigNo) { diff -puN coregrind/x86/core_arch.h~sigreturn-syscall coregrind/x86/core_arch.h --- valgrind/coregrind/x86/core_arch.h~sigreturn-syscall 2005-01-12 18:43:21.000000000 -0800 +++ valgrind-jeremy/coregrind/x86/core_arch.h 2005-01-12 18:43:21.000000000 -0800 @@ -350,6 +350,11 @@ struct arch_thread_aux { }; /* --------------------------------------------------------------------- + Signal stuff (should be plat) + ------------------------------------------------------------------ */ +void VGA_(signal_return)(ThreadId tid, Bool isRT); + +/* --------------------------------------------------------------------- Miscellaneous constants ------------------------------------------------------------------ */ _