Log signal info at time of receipt
When a fatal signal is received, we now write a message to the log that looks like this: F/libc ( 1540): Fatal signal 11 (SIGSEGV) at 0xdeadd00d (code=1) This is useful for debugging fatal signals that turn out not to be fatal. This also changes the signal reset from SIG_IGN to SIG_DFL, so that future non-fatal fatal signals are fatal. The code that blocked SIGUSR1 to avoid being interrupted by the GC has been removed. Also, fix minor issues in format_buffer(). Bug 5035703 Change-Id: I8940af47297b5dcf3cf33537e3483ca5334ed565
This commit is contained in:
parent
3a5d668e01
commit
ec92af8fe5
@ -87,13 +87,49 @@ static int socket_abstract_client(const char *name, int type)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void debugger_signal_handler(int n)
|
#include "linker_format.h"
|
||||||
|
#include <../libc/private/logd.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Writes a summary of the signal to the log file.
|
||||||
|
*
|
||||||
|
* We could be here as a result of native heap corruption, or while a
|
||||||
|
* mutex is being held, so we don't want to use any libc functions that
|
||||||
|
* could allocate memory or hold a lock.
|
||||||
|
*/
|
||||||
|
static void logSignalSummary(int signum, const siginfo_t* info)
|
||||||
|
{
|
||||||
|
char buffer[128];
|
||||||
|
|
||||||
|
char* signame;
|
||||||
|
switch (signum) {
|
||||||
|
case SIGILL: signame = "SIGILL"; break;
|
||||||
|
case SIGABRT: signame = "SIGABRT"; break;
|
||||||
|
case SIGBUS: signame = "SIGBUS"; break;
|
||||||
|
case SIGFPE: signame = "SIGFPE"; break;
|
||||||
|
case SIGSEGV: signame = "SIGSEGV"; break;
|
||||||
|
case SIGSTKFLT: signame = "SIGSTKFLT"; break;
|
||||||
|
case SIGPIPE: signame = "SIGPIPE"; break;
|
||||||
|
default: signame = "???"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
format_buffer(buffer, sizeof(buffer),
|
||||||
|
"Fatal signal %d (%s) at 0x%08x (code=%d)",
|
||||||
|
signum, signame, info->si_addr, info->si_code);
|
||||||
|
|
||||||
|
__libc_android_log_write(ANDROID_LOG_FATAL, "libc", buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Catches fatal signals so we can ask debuggerd to ptrace us before
|
||||||
|
* we crash.
|
||||||
|
*/
|
||||||
|
void debugger_signal_handler(int n, siginfo_t* info, void* unused)
|
||||||
{
|
{
|
||||||
unsigned tid;
|
unsigned tid;
|
||||||
int s;
|
int s;
|
||||||
|
|
||||||
/* avoid picking up GC interrupts */
|
logSignalSummary(n, info);
|
||||||
signal(SIGUSR1, SIG_IGN);
|
|
||||||
|
|
||||||
tid = gettid();
|
tid = gettid();
|
||||||
s = socket_abstract_client("android:debuggerd", SOCK_STREAM);
|
s = socket_abstract_client("android:debuggerd", SOCK_STREAM);
|
||||||
@ -117,16 +153,22 @@ void debugger_signal_handler(int n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* remove our net so we fault for real when we return */
|
/* remove our net so we fault for real when we return */
|
||||||
signal(n, SIG_IGN);
|
signal(n, SIG_DFL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void debugger_init()
|
void debugger_init()
|
||||||
{
|
{
|
||||||
signal(SIGILL, debugger_signal_handler);
|
struct sigaction act;
|
||||||
signal(SIGABRT, debugger_signal_handler);
|
memset(&act, 0, sizeof(act));
|
||||||
signal(SIGBUS, debugger_signal_handler);
|
act.sa_sigaction = debugger_signal_handler;
|
||||||
signal(SIGFPE, debugger_signal_handler);
|
act.sa_flags = SA_RESTART | SA_SIGINFO;
|
||||||
signal(SIGSEGV, debugger_signal_handler);
|
sigemptyset(&act.sa_mask);
|
||||||
signal(SIGSTKFLT, debugger_signal_handler);
|
|
||||||
signal(SIGPIPE, debugger_signal_handler);
|
sigaction(SIGILL, &act, NULL);
|
||||||
|
sigaction(SIGABRT, &act, NULL);
|
||||||
|
sigaction(SIGBUS, &act, NULL);
|
||||||
|
sigaction(SIGFPE, &act, NULL);
|
||||||
|
sigaction(SIGSEGV, &act, NULL);
|
||||||
|
sigaction(SIGSTKFLT, &act, NULL);
|
||||||
|
sigaction(SIGPIPE, &act, NULL);
|
||||||
}
|
}
|
||||||
|
@ -427,18 +427,20 @@ format_hex(char *buffer, size_t buffsize, uint64_t value, int isCap)
|
|||||||
static void
|
static void
|
||||||
out_vformat(Out *o, const char *format, va_list args)
|
out_vformat(Out *o, const char *format, va_list args)
|
||||||
{
|
{
|
||||||
int nn = 0, mm;
|
int nn = 0;
|
||||||
int padZero = 0;
|
|
||||||
int padLeft = 0;
|
|
||||||
char sign = '\0';
|
|
||||||
int width = -1;
|
|
||||||
int prec = -1;
|
|
||||||
size_t bytelen = sizeof(int);
|
|
||||||
const char* str;
|
|
||||||
int slen;
|
|
||||||
char buffer[32]; /* temporary buffer used to format numbers */
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
int mm;
|
||||||
|
int padZero = 0;
|
||||||
|
int padLeft = 0;
|
||||||
|
char sign = '\0';
|
||||||
|
int width = -1;
|
||||||
|
int prec = -1;
|
||||||
|
size_t bytelen = sizeof(int);
|
||||||
|
const char* str;
|
||||||
|
int slen;
|
||||||
|
char buffer[32]; /* temporary buffer used to format numbers */
|
||||||
|
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
/* first, find all characters that are not 0 or '%' */
|
/* first, find all characters that are not 0 or '%' */
|
||||||
@ -525,9 +527,6 @@ out_vformat(Out *o, const char *format, va_list args)
|
|||||||
bytelen = sizeof(ptrdiff_t);
|
bytelen = sizeof(ptrdiff_t);
|
||||||
c = format[nn++];
|
c = format[nn++];
|
||||||
break;
|
break;
|
||||||
case 'p':
|
|
||||||
bytelen = sizeof(void*);
|
|
||||||
c = format[nn++];
|
|
||||||
default:
|
default:
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
@ -543,7 +542,7 @@ out_vformat(Out *o, const char *format, va_list args)
|
|||||||
buffer[1] = '\0';
|
buffer[1] = '\0';
|
||||||
str = buffer;
|
str = buffer;
|
||||||
} else if (c == 'p') {
|
} else if (c == 'p') {
|
||||||
uint64_t value = (uint64_t)(ptrdiff_t) va_arg(args, void*);
|
uint64_t value = (uintptr_t) va_arg(args, void*);
|
||||||
buffer[0] = '0';
|
buffer[0] = '0';
|
||||||
buffer[1] = 'x';
|
buffer[1] = 'x';
|
||||||
format_hex(buffer + 2, sizeof buffer-2, value, 0);
|
format_hex(buffer + 2, sizeof buffer-2, value, 0);
|
||||||
@ -684,7 +683,7 @@ int main(void)
|
|||||||
utest_expect("-8123", "%d", -8123);
|
utest_expect("-8123", "%d", -8123);
|
||||||
utest_expect("16", "%hd", 0x7fff0010);
|
utest_expect("16", "%hd", 0x7fff0010);
|
||||||
utest_expect("16", "%hhd", 0x7fffff10);
|
utest_expect("16", "%hhd", 0x7fffff10);
|
||||||
utest_expect("68719476736", "%lld", 0x1000000000);
|
utest_expect("68719476736", "%lld", 0x1000000000LL);
|
||||||
utest_expect("70000", "%ld", 70000);
|
utest_expect("70000", "%ld", 70000);
|
||||||
utest_expect("0xb0001234", "%p", (void*)0xb0001234);
|
utest_expect("0xb0001234", "%p", (void*)0xb0001234);
|
||||||
utest_expect("12ab", "%x", 0x12ab);
|
utest_expect("12ab", "%x", 0x12ab);
|
||||||
@ -697,6 +696,9 @@ int main(void)
|
|||||||
utest_expect("1234 ", "%-8d", 1234);
|
utest_expect("1234 ", "%-8d", 1234);
|
||||||
utest_expect("abcdef ", "%-11s", "abcdef");
|
utest_expect("abcdef ", "%-11s", "abcdef");
|
||||||
utest_expect("something:1234", "%s:%d", "something", 1234);
|
utest_expect("something:1234", "%s:%d", "something", 1234);
|
||||||
|
utest_expect("005:5:05", "%03d:%d:%02d", 5, 5, 5);
|
||||||
|
utest_expect("5,0x0", "%d,%p", 5, NULL);
|
||||||
|
utest_expect("68719476736,6,7,8", "%lld,%d,%d,%d", 0x1000000000LL, 6, 7, 8);
|
||||||
return gFails != 0;
|
return gFails != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user