blob: 9bcbdb36a3735bdec916ca805d53be203d163244 [file] [log] [blame]
Josh Gaoe73c9322017-02-08 16:06:26 -08001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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
13 * distribution.
14 *
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
26 * SUCH DAMAGE.
27 */
28
Josh Gaoe1aa0ca2017-03-01 17:23:22 -080029#include <dirent.h>
30#include <fcntl.h>
31#include <poll.h>
32#include <pthread.h>
Josh Gaoe73c9322017-02-08 16:06:26 -080033#include <stddef.h>
34#include <sys/ucontext.h>
Josh Gaoe1aa0ca2017-03-01 17:23:22 -080035#include <syscall.h>
Josh Gaoe73c9322017-02-08 16:06:26 -080036#include <unistd.h>
37
Josh Gaoe1aa0ca2017-03-01 17:23:22 -080038#include <atomic>
Josh Gao2b2ae0c2017-08-21 14:31:17 -070039#include <memory>
Josh Gao70adac62018-02-22 11:38:33 -080040#include <mutex>
Josh Gaoe1aa0ca2017-03-01 17:23:22 -080041
42#include <android-base/file.h>
43#include <android-base/unique_fd.h>
Christopher Ferrisac225782017-04-25 11:23:10 -070044#include <async_safe/log.h>
Josh Gaoa48b41b2019-12-13 14:11:04 -080045#include <bionic/reserved_signals.h>
David Srbeckyb9cc4fb2019-04-05 18:23:32 +000046#include <unwindstack/DexFiles.h>
Christopher Ferris60eb1972019-01-15 15:18:43 -080047#include <unwindstack/JitDebug.h>
48#include <unwindstack/Maps.h>
Josh Gao2b2ae0c2017-08-21 14:31:17 -070049#include <unwindstack/Memory.h>
50#include <unwindstack/Regs.h>
Christopher Ferris60eb1972019-01-15 15:18:43 -080051#include <unwindstack/Unwinder.h>
Josh Gaoe1aa0ca2017-03-01 17:23:22 -080052
53#include "debuggerd/handler.h"
Josh Gao6f9eeec2018-09-12 13:55:47 -070054#include "handler/fallback.h"
Narayan Kamath2d377cd2017-05-10 10:58:59 +010055#include "tombstoned/tombstoned.h"
56#include "util.h"
Josh Gaoe1aa0ca2017-03-01 17:23:22 -080057
Josh Gaoc3706662017-08-29 13:08:32 -070058#include "libdebuggerd/backtrace.h"
59#include "libdebuggerd/tombstone.h"
Josh Gaoe73c9322017-02-08 16:06:26 -080060
Josh Gaoe1aa0ca2017-03-01 17:23:22 -080061using android::base::unique_fd;
62
Josh Gaoc531ed62018-01-24 14:23:42 -080063extern "C" bool __linker_enable_fallback_allocator();
Josh Gaoe1aa0ca2017-03-01 17:23:22 -080064extern "C" void __linker_disable_fallback_allocator();
65
66// This is incredibly sketchy to do inside of a signal handler, especially when libbacktrace
67// uses the C++ standard library throughout, but this code runs in the linker, so we'll be using
68// the linker's malloc instead of the libc one. Switch it out for a replacement, just in case.
69//
70// This isn't the default method of dumping because it can fail in cases such as address space
71// exhaustion.
72static void debuggerd_fallback_trace(int output_fd, ucontext_t* ucontext) {
Josh Gaoc531ed62018-01-24 14:23:42 -080073 if (!__linker_enable_fallback_allocator()) {
74 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "fallback allocator already in use");
75 return;
76 }
77
Josh Gao2b2ae0c2017-08-21 14:31:17 -070078 {
Christopher Ferris60eb1972019-01-15 15:18:43 -080079 std::unique_ptr<unwindstack::Regs> regs;
Josh Gao2b2ae0c2017-08-21 14:31:17 -070080
81 ThreadInfo thread;
82 thread.pid = getpid();
83 thread.tid = gettid();
84 thread.thread_name = get_thread_name(gettid());
David Srbeckyb9cc4fb2019-04-05 18:23:32 +000085 unwindstack::ArchEnum arch = unwindstack::Regs::CurrentArch();
86 thread.registers.reset(unwindstack::Regs::CreateFromUcontext(arch, ucontext));
Josh Gao2b2ae0c2017-08-21 14:31:17 -070087
88 // TODO: Create this once and store it in a global?
Christopher Ferris60eb1972019-01-15 15:18:43 -080089 unwindstack::UnwinderFromPid unwinder(kMaxFrames, getpid());
David Srbeckyb9cc4fb2019-04-05 18:23:32 +000090 if (unwinder.Init(arch)) {
Christopher Ferris60eb1972019-01-15 15:18:43 -080091 dump_backtrace_thread(output_fd, &unwinder, thread);
92 } else {
93 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Unable to init unwinder.");
94 }
Josh Gao2b2ae0c2017-08-21 14:31:17 -070095 }
Josh Gaoe1aa0ca2017-03-01 17:23:22 -080096 __linker_disable_fallback_allocator();
97}
98
99static void debuggerd_fallback_tombstone(int output_fd, ucontext_t* ucontext, siginfo_t* siginfo,
100 void* abort_message) {
Josh Gaoc531ed62018-01-24 14:23:42 -0800101 if (!__linker_enable_fallback_allocator()) {
102 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "fallback allocator already in use");
103 return;
104 }
105
Josh Gaoe1aa0ca2017-03-01 17:23:22 -0800106 engrave_tombstone_ucontext(output_fd, reinterpret_cast<uintptr_t>(abort_message), siginfo,
107 ucontext);
108 __linker_disable_fallback_allocator();
109}
110
111static void iterate_siblings(bool (*callback)(pid_t, int), int output_fd) {
112 pid_t current_tid = gettid();
113 char buf[BUFSIZ];
114 snprintf(buf, sizeof(buf), "/proc/%d/task", current_tid);
115 DIR* dir = opendir(buf);
116
117 if (!dir) {
Christopher Ferrisac225782017-04-25 11:23:10 -0700118 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to open %s: %s", buf, strerror(errno));
Josh Gaoe1aa0ca2017-03-01 17:23:22 -0800119 return;
120 }
121
122 struct dirent* ent;
123 while ((ent = readdir(dir))) {
124 char* end;
125 long tid = strtol(ent->d_name, &end, 10);
126 if (end == ent->d_name || *end != '\0') {
127 continue;
128 }
129
130 if (tid != current_tid) {
131 callback(tid, output_fd);
132 }
133 }
134 closedir(dir);
135}
136
Josh Gaoc531ed62018-01-24 14:23:42 -0800137static bool forward_output(int src_fd, int dst_fd, pid_t expected_tid) {
Josh Gaoe1aa0ca2017-03-01 17:23:22 -0800138 // Make sure the thread actually got the signal.
139 struct pollfd pfd = {
140 .fd = src_fd, .events = POLLIN,
141 };
142
143 // Wait for up to a second for output to start flowing.
144 if (poll(&pfd, 1, 1000) != 1) {
145 return false;
146 }
147
Josh Gaoc531ed62018-01-24 14:23:42 -0800148 pid_t tid;
149 if (TEMP_FAILURE_RETRY(read(src_fd, &tid, sizeof(tid))) != sizeof(tid)) {
150 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to read tid");
151 return false;
152 }
153
154 if (tid != expected_tid) {
155 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "received tid %d, expected %d", tid,
156 expected_tid);
157 return false;
158 }
159
Josh Gaoe1aa0ca2017-03-01 17:23:22 -0800160 while (true) {
161 char buf[512];
162 ssize_t rc = TEMP_FAILURE_RETRY(read(src_fd, buf, sizeof(buf)));
163 if (rc == 0) {
164 return true;
165 } else if (rc < 0) {
166 return false;
167 }
168
169 if (!android::base::WriteFully(dst_fd, buf, rc)) {
170 // We failed to write to tombstoned, but there's not much we can do.
171 // Keep reading from src_fd to keep things going.
172 continue;
173 }
174 }
175}
176
Josh Gaoc531ed62018-01-24 14:23:42 -0800177struct __attribute__((__packed__)) packed_thread_output {
178 int32_t tid;
179 int32_t fd;
180};
181
182static uint64_t pack_thread_fd(pid_t tid, int fd) {
183 packed_thread_output packed = {.tid = tid, .fd = fd};
184 uint64_t result;
185 static_assert(sizeof(packed) == sizeof(result));
186 memcpy(&result, &packed, sizeof(packed));
187 return result;
188}
189
190static std::pair<pid_t, int> unpack_thread_fd(uint64_t value) {
191 packed_thread_output result;
192 memcpy(&result, &value, sizeof(value));
193 return std::make_pair(result.tid, result.fd);
194}
195
Josh Gaoe1aa0ca2017-03-01 17:23:22 -0800196static void trace_handler(siginfo_t* info, ucontext_t* ucontext) {
Josh Gaoc531ed62018-01-24 14:23:42 -0800197 static std::atomic<uint64_t> trace_output(pack_thread_fd(-1, -1));
Josh Gaoe1aa0ca2017-03-01 17:23:22 -0800198
Josh Gao6f9eeec2018-09-12 13:55:47 -0700199 if (info->si_value.sival_ptr == kDebuggerdFallbackSivalPtrRequestDump) {
Josh Gaoe1aa0ca2017-03-01 17:23:22 -0800200 // Asked to dump by the original signal recipient.
Josh Gaoc531ed62018-01-24 14:23:42 -0800201 uint64_t val = trace_output.load();
202 auto [tid, fd] = unpack_thread_fd(val);
203 if (tid != gettid()) {
204 // We received some other thread's info request?
205 async_safe_format_log(ANDROID_LOG_ERROR, "libc",
206 "thread %d received output fd for thread %d?", gettid(), tid);
207 return;
208 }
Josh Gaoe1aa0ca2017-03-01 17:23:22 -0800209
Josh Gaoc531ed62018-01-24 14:23:42 -0800210 if (!trace_output.compare_exchange_strong(val, pack_thread_fd(-1, -1))) {
211 // Presumably, the timeout in forward_output expired, and the main thread moved on.
212 // If this happened, the main thread closed our fd for us, so just return.
213 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "cmpxchg for thread %d failed", gettid());
214 return;
215 }
216
217 // Write our tid to the output fd to let the main thread know that we're working.
218 if (TEMP_FAILURE_RETRY(write(fd, &tid, sizeof(tid))) == sizeof(tid)) {
219 debuggerd_fallback_trace(fd, ucontext);
220 } else {
221 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to write to output fd");
222 }
223
224 close(fd);
Josh Gaoe1aa0ca2017-03-01 17:23:22 -0800225 return;
226 }
227
228 // Only allow one thread to perform a trace at a time.
229 static pthread_mutex_t trace_mutex = PTHREAD_MUTEX_INITIALIZER;
230 int ret = pthread_mutex_trylock(&trace_mutex);
231 if (ret != 0) {
Christopher Ferrisac225782017-04-25 11:23:10 -0700232 async_safe_format_log(ANDROID_LOG_INFO, "libc", "pthread_mutex_try_lock failed: %s",
233 strerror(ret));
Josh Gaoe1aa0ca2017-03-01 17:23:22 -0800234 return;
235 }
236
237 // Fetch output fd from tombstoned.
238 unique_fd tombstone_socket, output_fd;
Narayan Kamatha73df602017-05-24 15:07:25 +0100239 if (!tombstoned_connect(getpid(), &tombstone_socket, &output_fd, kDebuggerdNativeBacktrace)) {
Josh Gaoe1aa0ca2017-03-01 17:23:22 -0800240 goto exit;
241 }
242
243 dump_backtrace_header(output_fd.get());
244
245 // Dump our own stack.
246 debuggerd_fallback_trace(output_fd.get(), ucontext);
247
248 // Send a signal to all of our siblings, asking them to dump their stack.
249 iterate_siblings(
Josh Gao2b2ae0c2017-08-21 14:31:17 -0700250 [](pid_t tid, int output_fd) {
251 // Use a pipe, to be able to detect situations where the thread gracefully exits before
252 // receiving our signal.
253 unique_fd pipe_read, pipe_write;
254 if (!Pipe(&pipe_read, &pipe_write)) {
255 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to create pipe: %s",
256 strerror(errno));
257 return false;
258 }
Josh Gaoe1aa0ca2017-03-01 17:23:22 -0800259
Josh Gaoc531ed62018-01-24 14:23:42 -0800260 uint64_t expected = pack_thread_fd(-1, -1);
Josh Gao08163cb2018-10-30 15:21:10 -0700261 int sent_fd = pipe_write.release();
262 if (!trace_output.compare_exchange_strong(expected, pack_thread_fd(tid, sent_fd))) {
Josh Gaoc531ed62018-01-24 14:23:42 -0800263 auto [tid, fd] = unpack_thread_fd(expected);
264 async_safe_format_log(ANDROID_LOG_ERROR, "libc",
265 "thread %d is already outputting to fd %d?", tid, fd);
Josh Gao08163cb2018-10-30 15:21:10 -0700266 close(sent_fd);
Josh Gaoc531ed62018-01-24 14:23:42 -0800267 return false;
268 }
Josh Gaoe1aa0ca2017-03-01 17:23:22 -0800269
Josh Gao2b2ae0c2017-08-21 14:31:17 -0700270 siginfo_t siginfo = {};
271 siginfo.si_code = SI_QUEUE;
Josh Gao6f9eeec2018-09-12 13:55:47 -0700272 siginfo.si_value.sival_ptr = kDebuggerdFallbackSivalPtrRequestDump;
Josh Gao2b2ae0c2017-08-21 14:31:17 -0700273 siginfo.si_pid = getpid();
274 siginfo.si_uid = getuid();
Josh Gaoe1aa0ca2017-03-01 17:23:22 -0800275
Josh Gaoa48b41b2019-12-13 14:11:04 -0800276 if (syscall(__NR_rt_tgsigqueueinfo, getpid(), tid, BIONIC_SIGNAL_DEBUGGER, &siginfo) != 0) {
Josh Gao2b2ae0c2017-08-21 14:31:17 -0700277 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to send trace signal to %d: %s",
278 tid, strerror(errno));
279 return false;
280 }
Josh Gaoe1aa0ca2017-03-01 17:23:22 -0800281
Josh Gaoc531ed62018-01-24 14:23:42 -0800282 bool success = forward_output(pipe_read.get(), output_fd, tid);
283 if (!success) {
284 async_safe_format_log(ANDROID_LOG_ERROR, "libc",
285 "timeout expired while waiting for thread %d to dump", tid);
286 }
287
288 // Regardless of whether the poll succeeds, check to see if the thread took fd ownership.
289 uint64_t post_wait = trace_output.exchange(pack_thread_fd(-1, -1));
290 if (post_wait != pack_thread_fd(-1, -1)) {
291 auto [tid, fd] = unpack_thread_fd(post_wait);
292 if (fd != -1) {
293 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "closing fd %d for thread %d", fd, tid);
294 close(fd);
295 }
Josh Gao2b2ae0c2017-08-21 14:31:17 -0700296 }
Josh Gaoe1aa0ca2017-03-01 17:23:22 -0800297
Josh Gao2b2ae0c2017-08-21 14:31:17 -0700298 return true;
299 },
300 output_fd.get());
Josh Gaoe1aa0ca2017-03-01 17:23:22 -0800301
302 dump_backtrace_footer(output_fd.get());
303 tombstoned_notify_completion(tombstone_socket.get());
304
305exit:
306 pthread_mutex_unlock(&trace_mutex);
307}
308
309static void crash_handler(siginfo_t* info, ucontext_t* ucontext, void* abort_message) {
Josh Gao2b2ae0c2017-08-21 14:31:17 -0700310 // Only allow one thread to handle a crash at a time (this can happen multiple times without
311 // exit, since tombstones can be requested without a real crash happening.)
Josh Gao70adac62018-02-22 11:38:33 -0800312 static std::recursive_mutex crash_mutex;
313 static int lock_count;
314
315 crash_mutex.lock();
316 if (lock_count++ > 0) {
Josh Gaod2b15dd2018-05-15 17:49:59 -0700317 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "recursed signal handler call, aborting");
318 signal(SIGABRT, SIG_DFL);
319 raise(SIGABRT);
320 sigset_t sigset;
321 sigemptyset(&sigset);
322 sigaddset(&sigset, SIGABRT);
323 sigprocmask(SIG_UNBLOCK, &sigset, nullptr);
324
325 // Just in case...
326 async_safe_format_log(ANDROID_LOG_ERROR, "libc", "abort didn't exit, exiting");
Josh Gao70adac62018-02-22 11:38:33 -0800327 _exit(1);
Josh Gaoe1aa0ca2017-03-01 17:23:22 -0800328 }
329
330 unique_fd tombstone_socket, output_fd;
Narayan Kamatha73df602017-05-24 15:07:25 +0100331 bool tombstoned_connected =
332 tombstoned_connect(getpid(), &tombstone_socket, &output_fd, kDebuggerdTombstone);
Josh Gaoe1aa0ca2017-03-01 17:23:22 -0800333 debuggerd_fallback_tombstone(output_fd.get(), ucontext, info, abort_message);
334 if (tombstoned_connected) {
335 tombstoned_notify_completion(tombstone_socket.get());
336 }
Josh Gao2b2ae0c2017-08-21 14:31:17 -0700337
Josh Gao70adac62018-02-22 11:38:33 -0800338 --lock_count;
339 crash_mutex.unlock();
Josh Gaoe1aa0ca2017-03-01 17:23:22 -0800340}
341
342extern "C" void debuggerd_fallback_handler(siginfo_t* info, ucontext_t* ucontext,
343 void* abort_message) {
Josh Gaoa48b41b2019-12-13 14:11:04 -0800344 if (info->si_signo == BIONIC_SIGNAL_DEBUGGER && info->si_value.sival_ptr != nullptr) {
Josh Gaoe1aa0ca2017-03-01 17:23:22 -0800345 return trace_handler(info, ucontext);
346 } else {
347 return crash_handler(info, ucontext, abort_message);
348 }
Josh Gaoe73c9322017-02-08 16:06:26 -0800349}