diff options
author | Thiago Macieira <[email protected]> | 2025-05-14 23:29:02 -0700 |
---|---|---|
committer | Thiago Macieira <[email protected]> | 2025-06-12 19:14:58 -0700 |
commit | 6489c41234806704c5e84a013959a28e1ee7aed4 (patch) | |
tree | 90061b5c2fddf387e780b9319b9ee0b7e9620057 | |
parent | 5d28c05ba896045cc2242b52bfd921dc3bacb0ec (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.cpp | 141 |
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))); |