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 <a.samirh78@gmail.com> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
parent
5d28c05ba8
commit
6489c41234
@ -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)));
|
||||
|
Loading…
x
Reference in New Issue
Block a user