2 * Copyright (C) 2008 The Android Open Source Project
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include <sys/prctl.h>
40 #include <sys/socket.h>
43 extern int tgkill(int tgid
, int tid
, int sig
);
45 void notify_gdb_of_libraries();
47 #define DEBUGGER_SOCKET_NAME "android:debuggerd"
51 DEBUGGER_ACTION_CRASH
,
52 // dump a tombstone file
53 DEBUGGER_ACTION_DUMP_TOMBSTONE
,
54 // dump a backtrace only back to the socket
55 DEBUGGER_ACTION_DUMP_BACKTRACE
,
58 /* message sent over the socket */
60 debugger_action_t action
;
64 #define RETRY_ON_EINTR(ret,cond) \
67 } while (ret < 0 && errno == EINTR)
69 // see man(2) prctl, specifically the section about PR_GET_NAME
70 #define MAX_TASK_NAME_LEN (16)
72 static int socket_abstract_client(const char *name
, int type
)
74 struct sockaddr_un addr
;
79 namelen
= strlen(name
);
81 // Test with length +1 for the *initial* '\0'.
82 if ((namelen
+ 1) > sizeof(addr
.sun_path
)) {
87 /* This is used for abstract socket namespace, we need
88 * an initial '\0' at the start of the Unix socket path.
90 * Note: The path in this case is *not* supposed to be
91 * '\0'-terminated. ("man 7 unix" for the gory details.)
93 memset (&addr
, 0, sizeof addr
);
94 addr
.sun_family
= AF_LOCAL
;
96 memcpy(addr
.sun_path
+ 1, name
, namelen
);
98 alen
= namelen
+ offsetof(struct sockaddr_un
, sun_path
) + 1;
100 s
= socket(AF_LOCAL
, type
, 0);
103 RETRY_ON_EINTR(err
,connect(s
, (struct sockaddr
*) &addr
, alen
));
112 #include "linker_format.h"
113 #include <../libc/private/logd.h>
116 * Writes a summary of the signal to the log file.
118 * We could be here as a result of native heap corruption, or while a
119 * mutex is being held, so we don't want to use any libc functions that
120 * could allocate memory or hold a lock.
122 static void logSignalSummary(int signum
, const siginfo_t
* info
)
125 char threadname
[MAX_TASK_NAME_LEN
+ 1]; // one more for termination
129 case SIGILL
: signame
= "SIGILL"; break;
130 case SIGABRT
: signame
= "SIGABRT"; break;
131 case SIGBUS
: signame
= "SIGBUS"; break;
132 case SIGFPE
: signame
= "SIGFPE"; break;
133 case SIGSEGV
: signame
= "SIGSEGV"; break;
134 case SIGSTKFLT
: signame
= "SIGSTKFLT"; break;
135 case SIGPIPE
: signame
= "SIGPIPE"; break;
136 default: signame
= "???"; break;
139 if (prctl(PR_GET_NAME
, (unsigned long)threadname
, 0, 0, 0) != 0) {
140 strcpy(threadname
, "<name unknown>");
142 // short names are null terminated by prctl, but the manpage
143 // implies that 16 byte names are not.
144 threadname
[MAX_TASK_NAME_LEN
] = 0;
146 format_buffer(buffer
, sizeof(buffer
),
147 "Fatal signal %d (%s) at 0x%08x (code=%d), thread %d (%s)",
148 signum
, signame
, info
->si_addr
, info
->si_code
, gettid(), threadname
);
150 __libc_android_log_write(ANDROID_LOG_FATAL
, "libc", buffer
);
154 * Catches fatal signals so we can ask debuggerd to ptrace us before
157 void debugger_signal_handler(int n
, siginfo_t
* info
, void* unused
)
163 logSignalSummary(n
, info
);
166 s
= socket_abstract_client(DEBUGGER_SOCKET_NAME
, SOCK_STREAM
);
169 /* debugger knows our pid from the credentials on the
170 * local socket but we need to tell it our tid. It
171 * is paranoid and will verify that we are giving a tid
172 * that's actually in our process
176 msg
.action
= DEBUGGER_ACTION_CRASH
;
178 RETRY_ON_EINTR(ret
, write(s
, &msg
, sizeof(msg
)));
179 if (ret
== sizeof(msg
)) {
180 /* if the write failed, there is no point to read on
181 * the file descriptor. */
182 RETRY_ON_EINTR(ret
, read(s
, &tid
, 1));
183 int savedErrno
= errno
;
184 notify_gdb_of_libraries();
189 /* read or write failed -- broken connection? */
190 format_buffer(msgbuf
, sizeof(msgbuf
),
191 "Failed while talking to debuggerd: %s", strerror(errno
));
192 __libc_android_log_write(ANDROID_LOG_FATAL
, "libc", msgbuf
);
197 /* socket failed; maybe process ran out of fds */
198 format_buffer(msgbuf
, sizeof(msgbuf
),
199 "Unable to open connection to debuggerd: %s", strerror(errno
));
200 __libc_android_log_write(ANDROID_LOG_FATAL
, "libc", msgbuf
);
203 /* remove our net so we fault for real when we return */
207 * These signals are not re-thrown when we resume. This means that
208 * crashing due to (say) SIGPIPE doesn't work the way you'd expect it
209 * to. We work around this by throwing them manually. We don't want
210 * to do this for *all* signals because it'll screw up the address for
211 * faults like SIGSEGV.
218 (void) tgkill(getpid(), gettid(), n
);
220 default: // SIGILL, SIGBUS, SIGSEGV
227 struct sigaction act
;
228 memset(&act
, 0, sizeof(act
));
229 act
.sa_sigaction
= debugger_signal_handler
;
230 act
.sa_flags
= SA_RESTART
| SA_SIGINFO
;
231 sigemptyset(&act
.sa_mask
);
233 sigaction(SIGILL
, &act
, NULL
);
234 sigaction(SIGABRT
, &act
, NULL
);
235 sigaction(SIGBUS
, &act
, NULL
);
236 sigaction(SIGFPE
, &act
, NULL
);
237 sigaction(SIGSEGV
, &act
, NULL
);
238 sigaction(SIGSTKFLT
, &act
, NULL
);
239 sigaction(SIGPIPE
, &act
, NULL
);