aboutsummaryrefslogtreecommitdiff
path: root/linux-user
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2023-08-22 22:07:41 -0700
committerRichard Henderson <richard.henderson@linaro.org>2023-10-18 15:34:34 -0700
commit4a6ebc19a7e2d013a0e2ca79452ea733b1d5b686 (patch)
tree82f422e651e38ed3343ae8043956c5aa211aebd9 /linux-user
parentf4e1168198a6306c3e337f2b91b1213f5bef52af (diff)
linux-user: Detect and report host SIGILL, SIGFPE, SIGTRAP
These signals, when not spoofed via kill(), are always bugs. Use die_from_signal to report this sensibly. Acked-by: Helge Deller <deller@gmx.de> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/signal.c44
1 files changed, 43 insertions, 1 deletions
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 706b8ac7a7..b67077f320 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -796,6 +796,43 @@ void die_from_signal(siginfo_t *info)
break;
}
break;
+ case SIGILL:
+ sig = "ILL";
+ switch (info->si_code) {
+ case ILL_ILLOPC:
+ code = "ILLOPC";
+ break;
+ case ILL_ILLOPN:
+ code = "ILLOPN";
+ break;
+ case ILL_ILLADR:
+ code = "ILLADR";
+ break;
+ case ILL_PRVOPC:
+ code = "PRVOPC";
+ break;
+ case ILL_PRVREG:
+ code = "PRVREG";
+ break;
+ case ILL_COPROC:
+ code = "COPROC";
+ break;
+ }
+ break;
+ case SIGFPE:
+ sig = "FPE";
+ switch (info->si_code) {
+ case FPE_INTDIV:
+ code = "INTDIV";
+ break;
+ case FPE_INTOVF:
+ code = "INTOVF";
+ break;
+ }
+ break;
+ case SIGTRAP:
+ sig = "TRAP";
+ break;
default:
snprintf(sigbuf, sizeof(sigbuf), "%d", info->si_signo);
sig = sigbuf;
@@ -900,7 +937,8 @@ static void host_signal_handler(int host_sig, siginfo_t *info, void *puc)
/*
* Non-spoofed SIGSEGV and SIGBUS are synchronous, and need special
- * handling wrt signal blocking and unwinding.
+ * handling wrt signal blocking and unwinding. Non-spoofed SIGILL,
+ * SIGFPE, SIGTRAP are always host bugs.
*/
if (info->si_code > 0) {
switch (host_sig) {
@@ -912,6 +950,10 @@ static void host_signal_handler(int host_sig, siginfo_t *info, void *puc)
host_sigbus_handler(cpu, info, uc);
sync_sig = true;
break;
+ case SIGILL:
+ case SIGFPE:
+ case SIGTRAP:
+ die_from_signal(info);
}
}