Index: qemu/linux-user/signal.c =================================================================== --- qemu.orig/linux-user/signal.c 2007-12-12 07:12:00.000000000 -0700 +++ qemu/linux-user/signal.c 2007-12-12 11:17:26.000000000 -0700 @@ -28,6 +28,7 @@ #include "qemu.h" #include "target_signal.h" +#include "qsignal.h" /* * Enable the DEBUG define and then set the individual DEBUG_* @@ -66,7 +67,7 @@ static void host_signal_handler(int host_signum, siginfo_t *info, void *puc); -static uint8_t host_to_target_signal_table[65] = { +uint8_t host_to_target_signal_table[65] = { [SIGHUP] = TARGET_SIGHUP, [SIGINT] = TARGET_SIGINT, [SIGQUIT] = TARGET_SIGQUIT, @@ -103,7 +104,7 @@ [SIGSYS] = TARGET_SIGSYS, /* next signals stay the same */ }; -static uint8_t target_to_host_signal_table[65]; +uint8_t target_to_host_signal_table[65]; static inline int on_sig_stack(unsigned long sp) { @@ -117,16 +118,6 @@ : on_sig_stack(sp) ? SS_ONSTACK : 0); } -static inline int host_to_target_signal(int sig) -{ - return host_to_target_signal_table[sig]; -} - -static inline int target_to_host_signal(int sig) -{ - return target_to_host_signal_table[sig]; -} - static void host_to_target_sigset_internal(target_sigset_t *d, const sigset_t *s) { @@ -334,13 +325,13 @@ first_free = q; } -/* abort execution with signal */ -void __attribute((noreturn)) force_sig(int sig) +/* abort execution with target signal */ +void __attribute((noreturn)) force_sig(int target_sig) { int host_sig; - host_sig = target_to_host_signal(sig); + host_sig = target_to_host_signal(target_sig); fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n", - sig, strsignal(host_sig)); + target_sig, strsignal(host_sig)); #if 1 _exit(-host_sig); #else @@ -355,23 +346,23 @@ #endif } -/* queue a signal so that it will be send to the virtual CPU as soon - as possible */ -int queue_signal(int sig, target_siginfo_t *info) +/* queue a target signal so that it will be sent to the virtual CPU as + soon as possible */ +int queue_signal(int target_sig, target_siginfo_t *info) { struct emulated_sigaction *k; struct sigqueue *q, **pq; abi_ulong handler; - debugf(DEBUG_SIGNAL, "queue_signal: sig=%d\n", sig); - k = &sigact_table[sig - 1]; + debugf(DEBUG_SIGNAL, "queue_signal: target_sig=%d\n", target_sig); + k = &sigact_table[target_sig - 1]; handler = k->sa._sa_handler; if (handler == TARGET_SIG_DFL) { /* default handler : ignore some signal. The other are fatal */ - if (sig != TARGET_SIGCHLD && - sig != TARGET_SIGURG && - sig != TARGET_SIGWINCH) { - force_sig(sig); + if (target_sig != TARGET_SIGCHLD && + target_sig != TARGET_SIGURG && + target_sig != TARGET_SIGWINCH) { + force_sig(target_sig); } else { return 0; /* indicate ignored */ } @@ -379,10 +370,10 @@ /* ignore signal */ return 0; } else if (handler == TARGET_SIG_ERR) { - force_sig(sig); + force_sig(target_sig); } else { pq = &k->first; - if (sig < TARGET_SIGRTMIN) { + if (target_sig < TARGET_SIGRTMIN) { /* if non real time signal, we queue exactly one signal */ if (!k->pending) q = &k->info; @@ -413,7 +404,7 @@ static void host_signal_handler(int host_signum, siginfo_t *info, void *puc) { - int sig; + int target_sig; target_siginfo_t tinfo; /* the CPU emulator uses some host signals to detect exceptions, @@ -424,12 +415,12 @@ } /* get target signal number */ - sig = host_to_target_signal(host_signum); - if (sig < 1 || sig > TARGET_NSIG) + target_sig = host_to_target_signal(host_signum); + if (target_sig < 1 || target_sig > TARGET_NSIG) return; - debugf(DEBUG_SIGNAL, "qemu: got signal %d\n", sig); + debugf(DEBUG_SIGNAL, "qemu: got target signal %d\n", target_sig); host_to_target_siginfo_noswap(&tinfo, info); - if (queue_signal(sig, &tinfo) == 1) { + if (queue_signal(target_sig, &tinfo) == 1) { /* interrupt the virtual CPU as soon as possible */ cpu_interrupt(global_env, CPU_INTERRUPT_EXIT); } @@ -1343,7 +1334,7 @@ badframe: unlock_user_struct(frame, frame_addr, 0); - force_sig(SIGSEGV /* , current */); + force_sig(TARGET_SIGSEGV /* , current */); return 0; } @@ -1384,7 +1375,7 @@ badframe: unlock_user_struct(frame, frame_addr, 0); - force_sig(SIGSEGV /* , current */); + force_sig(TARGET_SIGSEGV /* , current */); return 0; } @@ -1917,7 +1908,7 @@ return; do_sigsegv: unlock_user_struct(ucp, ucp_addr, 0); - force_sig(SIGSEGV); + force_sig(TARGET_SIGSEGV); } void sparc64_get_context(CPUSPARCState *env) @@ -2011,7 +2002,7 @@ return; do_sigsegv: unlock_user_struct(ucp, ucp_addr, 1); - force_sig(SIGSEGV); + force_sig(TARGET_SIGSEGV); } #endif #elif defined(TARGET_ABI_MIPSN64) @@ -2564,7 +2555,7 @@ give_sigsegv: unlock_user_struct(frame, frame_addr, 1); - force_sig(SIGSEGV); + force_sig(TARGET_SIGSEGV); } static void setup_rt_frame(int sig, struct emulated_sigaction *ka, @@ -2627,7 +2618,7 @@ give_sigsegv: unlock_user_struct(frame, frame_addr, 1); - force_sig(SIGSEGV); + force_sig(TARGET_SIGSEGV); } long do_sigreturn(CPUState *regs) Index: qemu/linux-user/syscall.c =================================================================== --- qemu.orig/linux-user/syscall.c 2007-12-12 07:12:14.000000000 -0700 +++ qemu/linux-user/syscall.c 2007-12-12 11:10:59.000000000 -0700 @@ -74,7 +74,9 @@ #include #include "qemu.h" +#include "qsignal.h" #include "qspinlock.h" +#include "debug.h" //#define DEBUG @@ -3709,9 +3711,14 @@ { int status; ret = get_errno(waitpid(arg1, &status, arg3)); - if (!is_error(ret) && arg2 - && put_user_s32(status, arg2)) - goto efault; + if (!is_error(ret) && arg2) { + if (WIFSIGNALED(status)) { + int hsig = host_to_target_signal(WTERMSIG(status)); + status = (status & ~0x7f) | hsig; + } + if (put_user_s32(status, arg2)) + goto efault; + } } break; #endif @@ -4030,7 +4037,7 @@ ret = 0; break; case TARGET_NR_kill: - ret = get_errno(kill(arg1, arg2)); + ret = get_errno(kill(arg1, target_to_host_signal(arg2))); break; case TARGET_NR_rename: { @@ -5020,23 +5027,30 @@ case TARGET_NR_wait4: { int status; - abi_long status_ptr = arg2; + abi_ulong status_addr = arg2; struct rusage rusage, *rusage_ptr; - abi_ulong target_rusage = arg4; - if (target_rusage) + abi_ulong target_rusage_addr = arg4; + + if (target_rusage_addr) rusage_ptr = &rusage; else rusage_ptr = NULL; + ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr)); - if (!is_error(ret)) { - if (status_ptr) { - if (put_user_s32(status, status_ptr)) - goto efault; + if (is_error(ret)) + goto fail; + + if (status_addr) { + if (WIFSIGNALED(status)) { + int hsig = host_to_target_signal(WTERMSIG(status)); + status = (status & ~0x7f) | hsig; } - if (target_rusage) - if (copy_to_user_rusage(target_rusage, &rusage)) - goto efault; + if (put_user_s32(status, status_addr)) + goto efault; } + if (target_rusage_addr) + if (copy_to_user_rusage(target_rusage_addr, &rusage)) + goto efault; } break; #ifdef TARGET_NR_swapoff Index: qemu/linux-user/qsignal.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ qemu/linux-user/qsignal.h 2007-12-12 07:12:14.000000000 -0700 @@ -0,0 +1,21 @@ +#ifndef QSIGNAL_H +#define QSIGNAL_H + +#include + + +extern uint8_t host_to_target_signal_table[]; +extern uint8_t target_to_host_signal_table[]; + + +static inline int host_to_target_signal(int sig) +{ + return host_to_target_signal_table[sig]; +} + +static inline int target_to_host_signal(int sig) +{ + return target_to_host_signal_table[sig]; +} + +#endif /* QSIGNAL_H */