summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <[email protected]>2025-05-14 23:29:02 -0700
committerThiago Macieira <[email protected]>2025-06-12 19:14:58 -0700
commit6489c41234806704c5e84a013959a28e1ee7aed4 (patch)
tree90061b5c2fddf387e780b9319b9ee0b7e9620057
parent5d28c05ba896045cc2242b52bfd921dc3bacb0ec (diff)
QTest::CrashHandler: print the Unix signal si_code name
It's easier to interpret an "SEGV_MAPERR", "FPE_INTDIV", or "ILL_ILLOPC" rather than "code 1". Alongside the decoded instruction pointer from the previous commit, we now get a message like: Received signal 11 (SIGSEGV), code SEGV_MAPERR, at address 0x00005637dd5c1346, for address 0x0000000000000004 Change-Id: Ic9f54e06fd2956fea3ccfffde7aa7b54167333b7 Reviewed-by: Ahmad Samir <[email protected]> Reviewed-by: Edward Welbourne <[email protected]>
-rw-r--r--src/testlib/qtestcrashhandler_unix.cpp141
1 files changed, 140 insertions, 1 deletions
diff --git a/src/testlib/qtestcrashhandler_unix.cpp b/src/testlib/qtestcrashhandler_unix.cpp
index d66a5423797..e6b845b84b3 100644
--- a/src/testlib/qtestcrashhandler_unix.cpp
+++ b/src/testlib/qtestcrashhandler_unix.cpp
@@ -503,6 +503,143 @@ void blockUnixSignals()
pthread_sigmask(SIG_BLOCK, &set, nullptr);
}
+static std::string_view unixSignalCodeToName(int signo, int code) noexcept
+{
+ switch (signo) {
+ case SIGFPE:
+ switch (code) {
+#ifdef FPE_INTDIV
+ case FPE_INTDIV: return "FPE_INTDIV"; // Integer divide by zero.
+#endif
+#ifdef FPE_INTOVF
+ case FPE_INTOVF: return "FPE_INTOVF"; // Integer overflow.
+#endif
+#ifdef FPE_FLTDIV
+ case FPE_FLTDIV: return "FPE_FLTDIV"; // Floating point divide by zero.
+#endif
+#ifdef FPE_FLTOVF
+ case FPE_FLTOVF: return "FPE_FLTOVF"; // Floating point overflow.
+#endif
+#ifdef FPE_FLTUND
+ case FPE_FLTUND: return "FPE_FLTUND"; // Floating point underflow.
+#endif
+#ifdef FPE_FLTRES
+ case FPE_FLTRES: return "FPE_FLTRES"; // Floating point inexact result.
+#endif
+#ifdef FPE_FLTINV
+ case FPE_FLTINV: return "FPE_FLTINV"; // Floating point invalid operation.
+#endif
+#ifdef FPE_FLTSUB
+ case FPE_FLTSUB: return "FPE_FLTSUB"; // Subscript out of range.
+#endif
+#ifdef FPE_FLTUNK
+ case FPE_FLTUNK: return "FPE_FLTUNK"; // Undiagnosed floating-point exception.
+#endif
+#ifdef FPE_CONDTRAP
+ case FPE_CONDTRAP: return "FPE_CONDTRAP"; // Trap on condition.
+#endif
+ }
+ break;
+
+ case SIGILL:
+ switch (code) {
+#ifdef ILL_ILLOPC
+ case ILL_ILLOPC: return "ILL_ILLOPC"; // Illegal opcode.
+#endif
+#ifdef ILL_ILLOPN
+ case ILL_ILLOPN: return "ILL_ILLOPN"; // Illegal operand.
+#endif
+#ifdef ILL_ILLADR
+ case ILL_ILLADR: return "ILL_ILLADR"; // Illegal addressing mode.
+#endif
+#ifdef ILL_ILLTRP
+ case ILL_ILLTRP: return "ILL_ILLTRP"; // Illegal trap.
+#endif
+#ifdef ILL_PRVOPC
+ case ILL_PRVOPC: return "ILL_PRVOPC"; // Privileged opcode.
+#endif
+#ifdef ILL_PRVREG
+ case ILL_PRVREG: return "ILL_PRVREG"; // Privileged register.
+#endif
+#ifdef ILL_COPROC
+ case ILL_COPROC: return "ILL_COPROC"; // Coprocessor error.
+#endif
+#ifdef ILL_BADSTK
+ case ILL_BADSTK: return "ILL_BADSTK"; // Internal stack error.
+#endif
+#ifdef ILL_BADIADDR
+ case ILL_BADIADDR: return "ILL_BADIADDR"; // Unimplemented instruction address.
+#endif
+ }
+ break;
+
+ case SIGSEGV:
+ switch (code) {
+#ifdef SEGV_MAPERR
+ case SEGV_MAPERR: return "SEGV_MAPERR"; // Address not mapped to object.
+#endif
+#ifdef SEGV_ACCERR
+ case SEGV_ACCERR: return "SEGV_ACCERR"; // Invalid permissions for mapped object.
+#endif
+#ifdef SEGV_BNDERR
+ // Intel MPX - deprecated
+ case SEGV_BNDERR: return "SEGV_BNDERR"; // Bounds checking failure.
+#endif
+#ifdef SEGV_PKUERR
+ // Intel PKRU
+ case SEGV_PKUERR: return "SEGV_PKUERR"; // Protection key checking failure.
+#endif
+#ifdef Q_PROCESSOR_SPARC
+ // these seem to be Sparc-specific on Linux
+# ifdef SEGV_ACCADI
+ case SEGV_ACCADI: return "SEGV_ACCADI"; // ADI not enabled for mapped object.
+# endif
+# ifdef SEGV_ADIDERR
+ case SEGV_ADIDERR: return "SEGV_ADIDERR"; // Disrupting MCD error.
+# endif
+# ifdef SEGV_ADIPERR
+ case SEGV_ADIPERR: return "SEGV_ADIPERR"; // Precise MCD exception.
+# endif
+#endif
+#ifdef Q_PROCESSOR_ARM
+# ifdef SEGV_MTEAERR
+ case SEGV_MTEAERR: return "SEGV_MTEAERR"; // Asynchronous ARM MTE error.
+# endif
+# ifdef SEGV_MTESERR
+ case SEGV_MTESERR: return "SEGV_MTESERR"; // Synchronous ARM MTE exception.
+# endif
+#endif
+#ifdef SEGV_CPERR
+ // seen on both AArch64 and x86 Linux
+ case SEGV_CPERR: return "SEGV_CPERR"; // Control protection fault
+#endif
+ }
+ break;
+
+ case SIGBUS:
+ switch (code) {
+#ifdef BUS_ADRALN
+ case BUS_ADRALN: return "BUS_ADRALN"; // Invalid address alignment.
+#endif
+#ifdef BUS_ADRERR
+ case BUS_ADRERR: return "BUS_ADRERR"; // Non-existant physical address.
+#endif
+#ifdef BUS_OBJERR
+ case BUS_OBJERR: return "BUS_OBJERR"; // Object specific hardware error.
+#endif
+#ifdef BUS_MCEERR_AR
+ case BUS_MCEERR_AR: return "BUS_MCEERR_AR"; // Hardware memory error: action required.
+#endif
+#ifdef BUS_MCEERR_AO
+ case BUS_MCEERR_AO: return "BUS_MCEERR_AO"; // Hardware memory error: action optional.
+#endif
+ }
+ break;
+ }
+
+ return {};
+}
+
template <typename T> static
std::enable_if_t<sizeof(std::declval<T>().si_pid) + sizeof(std::declval<T>().si_uid) >= 1>
printSentSignalInfo(T *info)
@@ -519,7 +656,9 @@ printCrashingSignalInfo(T *info, quintptr pc)
auto toHexString = [](quintptr u, HexString &&r = {}) {
return asyncSafeToHexString(u, r.data());
};
- writeToStderr(", code ", asyncSafeToString(info->si_code));
+
+ std::string_view name = unixSignalCodeToName(info->si_signo, info->si_code);
+ writeToStderr(", code ", name.size() ? name : asyncSafeToString(info->si_code));
if (pc)
writeToStderr(", at instruction address ", toHexString(pc));
writeToStderr(", accessing address ", toHexString(quintptr(info->si_addr)));