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
39 #include <sys/socket.h>
42 void notify_gdb_of_libraries();
44 #define RETRY_ON_EINTR(ret,cond) \
47 } while (ret < 0 && errno == EINTR)
50 static int socket_abstract_client(const char *name
, int type
)
52 struct sockaddr_un addr
;
57 namelen
= strlen(name
);
59 // Test with length +1 for the *initial* '\0'.
60 if ((namelen
+ 1) > sizeof(addr
.sun_path
)) {
65 /* This is used for abstract socket namespace, we need
66 * an initial '\0' at the start of the Unix socket path.
68 * Note: The path in this case is *not* supposed to be
69 * '\0'-terminated. ("man 7 unix" for the gory details.)
71 memset (&addr
, 0, sizeof addr
);
72 addr
.sun_family
= AF_LOCAL
;
74 memcpy(addr
.sun_path
+ 1, name
, namelen
);
76 alen
= namelen
+ offsetof(struct sockaddr_un
, sun_path
) + 1;
78 s
= socket(AF_LOCAL
, type
, 0);
81 RETRY_ON_EINTR(err
,connect(s
, (struct sockaddr
*) &addr
, alen
));
90 #include "linker_format.h"
91 #include <../libc/private/logd.h>
94 * Writes a summary of the signal to the log file.
96 * We could be here as a result of native heap corruption, or while a
97 * mutex is being held, so we don't want to use any libc functions that
98 * could allocate memory or hold a lock.
100 static void logSignalSummary(int signum
, const siginfo_t
* info
)
106 case SIGILL
: signame
= "SIGILL"; break;
107 case SIGABRT
: signame
= "SIGABRT"; break;
108 case SIGBUS
: signame
= "SIGBUS"; break;
109 case SIGFPE
: signame
= "SIGFPE"; break;
110 case SIGSEGV
: signame
= "SIGSEGV"; break;
111 case SIGSTKFLT
: signame
= "SIGSTKFLT"; break;
112 case SIGPIPE
: signame
= "SIGPIPE"; break;
113 default: signame
= "???"; break;
116 format_buffer(buffer
, sizeof(buffer
),
117 "Fatal signal %d (%s) at 0x%08x (code=%d)",
118 signum
, signame
, info
->si_addr
, info
->si_code
);
120 __libc_android_log_write(ANDROID_LOG_FATAL
, "libc", buffer
);
124 * Catches fatal signals so we can ask debuggerd to ptrace us before
127 void debugger_signal_handler(int n
, siginfo_t
* info
, void* unused
)
132 logSignalSummary(n
, info
);
135 s
= socket_abstract_client("android:debuggerd", SOCK_STREAM
);
138 /* debugger knows our pid from the credentials on the
139 * local socket but we need to tell it our tid. It
140 * is paranoid and will verify that we are giving a tid
141 * that's actually in our process
145 RETRY_ON_EINTR(ret
, write(s
, &tid
, sizeof(unsigned)));
146 if (ret
== sizeof(unsigned)) {
147 /* if the write failed, there is no point to read on
148 * the file descriptor. */
149 RETRY_ON_EINTR(ret
, read(s
, &tid
, 1));
150 notify_gdb_of_libraries();
155 /* remove our net so we fault for real when we return */
161 struct sigaction act
;
162 memset(&act
, 0, sizeof(act
));
163 act
.sa_sigaction
= debugger_signal_handler
;
164 act
.sa_flags
= SA_RESTART
| SA_SIGINFO
;
165 sigemptyset(&act
.sa_mask
);
167 sigaction(SIGILL
, &act
, NULL
);
168 sigaction(SIGABRT
, &act
, NULL
);
169 sigaction(SIGBUS
, &act
, NULL
);
170 sigaction(SIGFPE
, &act
, NULL
);
171 sigaction(SIGSEGV
, &act
, NULL
);
172 sigaction(SIGSTKFLT
, &act
, NULL
);
173 sigaction(SIGPIPE
, &act
, NULL
);