am 8fe46b47: am f2dc7d17: Merge "Pass si_code through to debuggerd."
* commit '8fe46b47c2bc3b47f44580dc0e3d21335c71462d': Pass si_code through to debuggerd.
This commit is contained in:
commit
12e848eb43
@ -64,6 +64,9 @@ struct debugger_msg_t {
|
|||||||
|
|
||||||
// version 2 added:
|
// version 2 added:
|
||||||
uintptr_t abort_msg_address;
|
uintptr_t abort_msg_address;
|
||||||
|
|
||||||
|
// version 3 added:
|
||||||
|
int32_t original_si_code;
|
||||||
};
|
};
|
||||||
|
|
||||||
// see man(2) prctl, specifically the section about PR_GET_NAME
|
// see man(2) prctl, specifically the section about PR_GET_NAME
|
||||||
@ -199,11 +202,44 @@ static bool have_siginfo(int signum) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void send_debuggerd_packet(siginfo_t* info) {
|
||||||
|
int s = socket_abstract_client(DEBUGGER_SOCKET_NAME, SOCK_STREAM);
|
||||||
|
if (s == -1) {
|
||||||
|
__libc_format_log(ANDROID_LOG_FATAL, "libc", "Unable to open connection to debuggerd: %s",
|
||||||
|
strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// debuggerd knows our pid from the credentials on the
|
||||||
|
// local socket but we need to tell it the tid of the crashing thread.
|
||||||
|
// debuggerd will be paranoid and verify that we sent a tid
|
||||||
|
// that's actually in our process.
|
||||||
|
debugger_msg_t msg;
|
||||||
|
msg.action = DEBUGGER_ACTION_CRASH;
|
||||||
|
msg.tid = gettid();
|
||||||
|
msg.abort_msg_address = reinterpret_cast<uintptr_t>(gAbortMessage);
|
||||||
|
msg.original_si_code = (info != NULL) ? info->si_code : 0;
|
||||||
|
int ret = TEMP_FAILURE_RETRY(write(s, &msg, sizeof(msg)));
|
||||||
|
if (ret == sizeof(msg)) {
|
||||||
|
char debuggerd_ack;
|
||||||
|
ret = TEMP_FAILURE_RETRY(read(s, &debuggerd_ack, 1));
|
||||||
|
int saved_errno = errno;
|
||||||
|
notify_gdb_of_libraries();
|
||||||
|
errno = saved_errno;
|
||||||
|
} else {
|
||||||
|
// read or write failed -- broken connection?
|
||||||
|
__libc_format_log(ANDROID_LOG_FATAL, "libc", "Failed while talking to debuggerd: %s",
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
close(s);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Catches fatal signals so we can ask debuggerd to ptrace us before
|
* Catches fatal signals so we can ask debuggerd to ptrace us before
|
||||||
* we crash.
|
* we crash.
|
||||||
*/
|
*/
|
||||||
void debuggerd_signal_handler(int signal_number, siginfo_t* info, void*) {
|
static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void*) {
|
||||||
// It's possible somebody cleared the SA_SIGINFO flag, which would mean
|
// It's possible somebody cleared the SA_SIGINFO flag, which would mean
|
||||||
// our "info" arg holds an undefined value.
|
// our "info" arg holds an undefined value.
|
||||||
if (!have_siginfo(signal_number)) {
|
if (!have_siginfo(signal_number)) {
|
||||||
@ -212,38 +248,7 @@ void debuggerd_signal_handler(int signal_number, siginfo_t* info, void*) {
|
|||||||
|
|
||||||
log_signal_summary(signal_number, info);
|
log_signal_summary(signal_number, info);
|
||||||
|
|
||||||
int s = socket_abstract_client(DEBUGGER_SOCKET_NAME, SOCK_STREAM);
|
send_debuggerd_packet(info);
|
||||||
if (s != -1) {
|
|
||||||
// debuggerd knows our pid from the credentials on the
|
|
||||||
// local socket but we need to tell it the tid of the crashing thread.
|
|
||||||
// debuggerd will be paranoid and verify that we sent a tid
|
|
||||||
// that's actually in our process.
|
|
||||||
debugger_msg_t msg;
|
|
||||||
msg.action = DEBUGGER_ACTION_CRASH;
|
|
||||||
msg.tid = gettid();
|
|
||||||
msg.abort_msg_address = reinterpret_cast<uintptr_t>(gAbortMessage);
|
|
||||||
int ret = TEMP_FAILURE_RETRY(write(s, &msg, sizeof(msg)));
|
|
||||||
if (ret == sizeof(msg)) {
|
|
||||||
// If the write failed, there is no point trying to read a response.
|
|
||||||
char debuggerd_ack;
|
|
||||||
ret = TEMP_FAILURE_RETRY(read(s, &debuggerd_ack, 1));
|
|
||||||
int saved_errno = errno;
|
|
||||||
notify_gdb_of_libraries();
|
|
||||||
errno = saved_errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret < 0) {
|
|
||||||
// read or write failed -- broken connection?
|
|
||||||
__libc_format_log(ANDROID_LOG_FATAL, "libc", "Failed while talking to debuggerd: %s",
|
|
||||||
strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
close(s);
|
|
||||||
} else {
|
|
||||||
// socket failed; maybe process ran out of fds?
|
|
||||||
__libc_format_log(ANDROID_LOG_FATAL, "libc", "Unable to open connection to debuggerd: %s",
|
|
||||||
strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove our net so we fault for real when we return.
|
// Remove our net so we fault for real when we return.
|
||||||
signal(signal_number, SIG_DFL);
|
signal(signal_number, SIG_DFL);
|
||||||
@ -251,8 +256,9 @@ void debuggerd_signal_handler(int signal_number, siginfo_t* info, void*) {
|
|||||||
// These signals are not re-thrown when we resume. This means that
|
// These signals are not re-thrown when we resume. This means that
|
||||||
// crashing due to (say) SIGPIPE doesn't work the way you'd expect it
|
// crashing due to (say) SIGPIPE doesn't work the way you'd expect it
|
||||||
// to. We work around this by throwing them manually. We don't want
|
// to. We work around this by throwing them manually. We don't want
|
||||||
// to do this for *all* signals because it'll screw up the address for
|
// to do this for *all* signals because it'll screw up the si_addr for
|
||||||
// faults like SIGSEGV.
|
// faults like SIGSEGV. It does screw up the si_code, which is why we
|
||||||
|
// passed that to debuggerd above.
|
||||||
switch (signal_number) {
|
switch (signal_number) {
|
||||||
case SIGABRT:
|
case SIGABRT:
|
||||||
case SIGFPE:
|
case SIGFPE:
|
||||||
@ -267,7 +273,7 @@ void debuggerd_signal_handler(int signal_number, siginfo_t* info, void*) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void debuggerd_init() {
|
__LIBC_HIDDEN__ void debuggerd_init() {
|
||||||
struct sigaction action;
|
struct sigaction action;
|
||||||
memset(&action, 0, sizeof(action));
|
memset(&action, 0, sizeof(action));
|
||||||
sigemptyset(&action.sa_mask);
|
sigemptyset(&action.sa_mask);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user