constchar* 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"; #ifdefined(SIGSTKFLT) case SIGSTKFLT: return"SIGSTKFLT"; #endif case SIGTRAP: return"SIGTRAP";
} return"??";
}
constchar* 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"; #ifdefined(SEGV_BNDERR) case SEGV_BNDERR: return"SEGV_BNDERR"; #endif
} 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"; #ifdefined(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"; #ifdefined(SI_SIGIO) case SI_SIGIO: return"SI_SIGIO"; #endif #ifdefined(SI_TKILL) case SI_TKILL: return"SI_TKILL"; #endif
} // Then give up... return"?";
}
void DumpX86Flags(std::ostream& os, uint32_t flags) const; // Print some of the information from the status register (CPSR on ARMv7, PSTATE on ARMv8). template <typename RegisterType> void DumpArmStatusRegister(std::ostream& os, RegisterType status_register) const;
DumpRegister32(os, "cpsr", context.arm_cpsr);
DumpArmStatusRegister(os, context.arm_cpsr);
os << '\n'; #elifdefined(__linux__) && defined(__aarch64__) for (size_t i = 0; i <= 30; ++i) {
std::string reg_name = "x" + std::to_string(i);
DumpRegister64(os, reg_name.c_str(), context.regs[i]); if (i % 4 == 3) {
os << '\n';
}
}
os << '\n';
DumpRegister64(os, "sp", context.sp);
DumpRegister64(os, "pc", context.pc);
os << '\n';
DumpRegister64(os, "pstate", context.pstate);
DumpArmStatusRegister(os, context.pstate);
os << '\n'; #else
os << "Unknown architecture/word size/OS in ucontext dump"; #endif
}
os << " ["; if ((status_register & kFlagN) != 0) {
os << " N";
} if ((status_register & kFlagZ) != 0) {
os << " Z";
} if ((status_register & kFlagC) != 0) {
os << " C";
} if ((status_register & kFlagV) != 0) {
os << " V";
}
os << " ]";
}
int GetTimeoutSignal() { #ifdefined(__APPLE__) // Mac does not support realtime signals.
UNUSED(kUseSigRTTimeout); return -1; #else return kUseSigRTTimeout ? (SIGRTMIN + 2) : -1; #endif
}
if (dump_on_stderr) { // Note: We are using cerr directly instead of LOG macros to ensure even just partial output // makes it out. That means we lose the "dalvikvm..." prefix, but that is acceptable // considering this is an abort situation.
logger(std::cerr);
} else {
logger(LOG_STREAM(FATAL_WITHOUT_ABORT));
} if (kIsDebugBuild && signal_number == SIGSEGV) {
PrintFileToLog("/proc/self/maps", android::base::LogSeverity::FATAL_WITHOUT_ABORT);
}
Runtime* runtime = Runtime::Current(); if (runtime != nullptr) { if (handle_timeout_signal && IsTimeoutSignal(signal_number)) { // Special timeout signal. Try to dump all threads. // Note: Do not use DumpForSigQuit, as that might disable native unwind, but the native parts // are of value here.
runtime->GetThreadList()->Dump(std::cerr, kDumpNativeStackOnTimeout);
std::cerr << std::endl;
}
// Local _static_ storing the currently handled signal (or -1). staticint handling_unexpected_signal = -1;
// Whether the dump code should be run under the unexpected-signal lock. For diagnostics we // allow recursive unexpected-signals in certain cases - avoid a deadlock. bool grab_lock = true;
if (handling_unexpected_signal != -1) {
LogHelper::LogLineLowStack(__FILE__,
__LINE__,
::android::base::FATAL_WITHOUT_ABORT, "HandleUnexpectedSignal reentered\n"); // Print the signal number. Don't use any standard functions, just some arithmetic. Just best // effort, with a minimal buffer. if (0 < signal_number && signal_number < 100) { char buf[] = { ' ', 'S', static_cast<char>('0' + (signal_number / 10)), static_cast<char>('0' + (signal_number % 10)), '\n', 0 };
LogHelper::LogLineLowStack(__FILE__,
__LINE__,
::android::base::FATAL_WITHOUT_ABORT,
buf);
} if (handle_timeout_signal) { if (IsTimeoutSignal(signal_number)) { // Ignore a recursive timeout. return;
}
} // If we were handling a timeout signal, try to go on. Otherwise hard-exit. // This relies on the expectation that we'll only ever get one timeout signal. if (!handle_timeout_signal || handling_unexpected_signal != GetTimeoutSignal()) {
_exit(1);
}
grab_lock = false; // The "outer" handling instance already holds the lock.
}
handling_unexpected_signal = signal_number;
gAborting++; // set before taking any locks
if (grab_lock) {
MutexLock mu(Thread::Current(), *Locks::unexpected_signal_lock_);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.