/* * Copyright (c) 2020 Amlogic, Inc. All rights reserved. * * This source code is subject to the terms and conditions defined in the * file 'LICENSE' which is part of this source code package. * * Description: */ #define LOG_TAG "AmlMpSignalHandler" #include "AmlMpSignalHandler.h" #include "AmlMpLog.h" #include #include #include #include #include #include #include static const char* mName = LOG_TAG; namespace aml_mp { int AmlMpSignalHandler::installSignalHandlers() { int ret = 0; struct sigaction act, old; memset(&act, 0, sizeof(struct sigaction)); sigemptyset(&act.sa_mask); act.sa_flags |= SA_SIGINFO | SA_ONSTACK; act.sa_sigaction = unexpectedSignalHandler; ret = sigaction(SIGABRT, &act, &old); if (ret == 0) instance().mOldSignalHandlers[SIGABRT] = old.sa_handler; ret += sigaction(SIGBUS, &act, &old); if (ret == 0) instance().mOldSignalHandlers[SIGBUS] = old.sa_handler; ret += sigaction(SIGFPE, &act, &old); if (ret == 0) instance().mOldSignalHandlers[SIGFPE] = old.sa_handler; ret += sigaction(SIGILL, &act, &old); if (ret == 0) instance().mOldSignalHandlers[SIGILL] = old.sa_handler; ret += sigaction(SIGSEGV, &act, &old); if (ret == 0) instance().mOldSignalHandlers[SIGSEGV] = old.sa_handler; ret += sigaction(SIGTRAP, &act, &old); if (ret == 0) instance().mOldSignalHandlers[SIGTRAP] = old.sa_handler; return 0; } void AmlMpSignalHandler::unexpectedSignalHandler(int signal_number, siginfo_t *info, void* ) { static bool handlingUnexpectedSignal = false; if (handlingUnexpectedSignal) { MLOGE("HandleUnexpectedSignal reentered\n"); _exit(1); } handlingUnexpectedSignal = true; bool has_address = (signal_number == SIGILL || signal_number == SIGBUS || signal_number == SIGFPE || signal_number == SIGSEGV); std::stringstream ss; ss << "\n *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n" << " Fatal signal " << signal_number << " (" << getSignalName(signal_number) << "), code " << info->si_code << " (" << getSignalCodeName(signal_number, info->si_code) << ")"; if (has_address) { ss << ", fault addr " << std::hex << info->si_addr << "\n"; } instance().dumpstack(ss); MLOGE("%s", ss.str().c_str()); fprintf(stderr, "%s\n", ss.str().c_str()); struct sigaction action; memset(&action, 0, sizeof(action)); sigemptyset(&action.sa_mask); action.sa_handler = instance().mOldSignalHandlers[signal_number]; sigaction(signal_number, &action, NULL); // ...and re-raise so we die with the appropriate status. kill(getpid(), signal_number); } const char* AmlMpSignalHandler::getSignalName(int signal_number) { switch (signal_number) { case SIGABRT: return "SIGABRT"; case SIGBUS: return "SIGBUS"; case SIGFPE: return "SIGFPE"; case SIGILL: return "SIGILL"; case SIGPIPE: return "SIGPIPE"; case SIGSEGV: return "SIGSEGV"; #if defined(SIGSTKFLT) case SIGSTKFLT: return "SIGSTKFLT"; #endif case SIGTRAP: return "SIGTRAP"; } return "??"; } const char* AmlMpSignalHandler::getSignalCodeName(int signal_number, int signal_code) { // Try the signal-specific codes... switch (signal_number) { case SIGILL: switch (signal_code) { case ILL_ILLOPC: return "ILL_ILLOPC"; case ILL_ILLOPN: return "ILL_ILLOPN"; case ILL_ILLADR: return "ILL_ILLADR"; case ILL_ILLTRP: return "ILL_ILLTRP"; case ILL_PRVOPC: return "ILL_PRVOPC"; case ILL_PRVREG: return "ILL_PRVREG"; case ILL_COPROC: return "ILL_COPROC"; case ILL_BADSTK: return "ILL_BADSTK"; } break; case SIGBUS: switch (signal_code) { case BUS_ADRALN: return "BUS_ADRALN"; case BUS_ADRERR: return "BUS_ADRERR"; case BUS_OBJERR: return "BUS_OBJERR"; } break; case SIGFPE: switch (signal_code) { case FPE_INTDIV: return "FPE_INTDIV"; case FPE_INTOVF: return "FPE_INTOVF"; case FPE_FLTDIV: return "FPE_FLTDIV"; case FPE_FLTOVF: return "FPE_FLTOVF"; case FPE_FLTUND: return "FPE_FLTUND"; case FPE_FLTRES: return "FPE_FLTRES"; case FPE_FLTINV: return "FPE_FLTINV"; case FPE_FLTSUB: return "FPE_FLTSUB"; } break; case SIGSEGV: switch (signal_code) { case SEGV_MAPERR: return "SEGV_MAPERR"; case SEGV_ACCERR: return "SEGV_ACCERR"; } break; case SIGTRAP: switch (signal_code) { case TRAP_BRKPT: return "TRAP_BRKPT"; case TRAP_TRACE: return "TRAP_TRACE"; } break; } // Then the other codes... switch (signal_code) { case SI_USER: return "SI_USER"; #if defined(SI_KERNEL) case SI_KERNEL: return "SI_KERNEL"; #endif case SI_QUEUE: return "SI_QUEUE"; case SI_TIMER: return "SI_TIMER"; case SI_MESGQ: return "SI_MESGQ"; case SI_ASYNCIO: return "SI_ASYNCIO"; #if defined(SI_SIGIO) case SI_SIGIO: return "SI_SIGIO"; #endif #if defined(SI_TKILL) case SI_TKILL: return "SI_TKILL"; #endif } // Then give up... return "?"; } void AmlMpSignalHandler::dumpstack(std::ostream& os) { char* stack[20] = {0}; int depth = backtrace(reinterpret_cast(stack), sizeof(stack)/sizeof(stack[0])); if (depth) { char** symbols = backtrace_symbols(reinterpret_cast(stack), depth); if (symbols) { os << std::dec; for (int i = 0; i < depth; i++) { os << "#" << std::setw(2) << std::left << i + 1 << " " << demangleSymbol(symbols[i]) << "\n"; } } free(symbols); } } std::string AmlMpSignalHandler::demangleSymbol(const char* symbol) { std::string result; const char* p = strchr(symbol, '('); if (p == nullptr) { return symbol; } std::string libraryName(symbol, p - symbol); result.append(libraryName); const char* pSymbolName = p +1; p = strchr(pSymbolName, '+'); if (p == nullptr) { return symbol; } std::string symbolName(pSymbolName, p - pSymbolName); int status; char* demangleResult = abi::__cxa_demangle(symbolName.c_str(), nullptr, nullptr, &status); if (status == 0) { result.append("("); result.append(demangleResult); result.append(p); } free(demangleResult); return result; } }