blob: 2921350584afea07d11be1e959f6269cb0ea859d [file] [log] [blame]
Jeff Brown053b8652012-06-06 16:25:03 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stddef.h>
18#include <stdbool.h>
19#include <stdlib.h>
20#include <signal.h>
21#include <string.h>
22#include <stdio.h>
23#include <fcntl.h>
24#include <errno.h>
25#include <dirent.h>
26#include <time.h>
27#include <sys/ptrace.h>
28#include <sys/stat.h>
29
30#include <private/android_filesystem_config.h>
31
Colin Cross9227bd32013-07-23 16:59:20 -070032#include <log/logger.h>
Jeff Brown053b8652012-06-06 16:25:03 -070033#include <cutils/properties.h>
34
Jeff Brown053b8652012-06-06 16:25:03 -070035#include <corkscrew/backtrace.h>
36
Christopher Tateded2e5a2013-03-19 13:12:23 -070037#include <sys/socket.h>
38#include <linux/un.h>
39
rpcraigf1186f32012-07-19 09:38:06 -040040#include <selinux/android.h>
rpcraigf1186f32012-07-19 09:38:06 -040041
Jeff Brown053b8652012-06-06 16:25:03 -070042#include "machine.h"
43#include "tombstone.h"
44#include "utility.h"
45
46#define STACK_DEPTH 32
47#define STACK_WORDS 16
48
49#define MAX_TOMBSTONES 10
50#define TOMBSTONE_DIR "/data/tombstones"
51
Christopher Tateded2e5a2013-03-19 13:12:23 -070052/* Must match the path defined in NativeCrashListener.java */
53#define NCRASH_SOCKET_PATH "/data/system/ndebugsocket"
54
Jeff Brown053b8652012-06-06 16:25:03 -070055#define typecheck(x,y) { \
56 typeof(x) __dummy1; \
57 typeof(y) __dummy2; \
58 (void)(&__dummy1 == &__dummy2); }
59
60
61static bool signal_has_address(int sig) {
62 switch (sig) {
63 case SIGILL:
64 case SIGFPE:
65 case SIGSEGV:
66 case SIGBUS:
67 return true;
68 default:
69 return false;
70 }
71}
72
73static const char *get_signame(int sig)
74{
75 switch(sig) {
76 case SIGILL: return "SIGILL";
77 case SIGABRT: return "SIGABRT";
78 case SIGBUS: return "SIGBUS";
79 case SIGFPE: return "SIGFPE";
80 case SIGSEGV: return "SIGSEGV";
81 case SIGPIPE: return "SIGPIPE";
Chris Dearman231e3c82012-08-10 17:06:20 -070082#ifdef SIGSTKFLT
Jeff Brown053b8652012-06-06 16:25:03 -070083 case SIGSTKFLT: return "SIGSTKFLT";
Chris Dearman231e3c82012-08-10 17:06:20 -070084#endif
Jeff Brown053b8652012-06-06 16:25:03 -070085 case SIGSTOP: return "SIGSTOP";
86 default: return "?";
87 }
88}
89
90static const char *get_sigcode(int signo, int code)
91{
Elliott Hughes8f7d4432012-12-10 10:29:05 -080092 // Try the signal-specific codes...
Jeff Brown053b8652012-06-06 16:25:03 -070093 switch (signo) {
94 case SIGILL:
95 switch (code) {
96 case ILL_ILLOPC: return "ILL_ILLOPC";
97 case ILL_ILLOPN: return "ILL_ILLOPN";
98 case ILL_ILLADR: return "ILL_ILLADR";
99 case ILL_ILLTRP: return "ILL_ILLTRP";
100 case ILL_PRVOPC: return "ILL_PRVOPC";
101 case ILL_PRVREG: return "ILL_PRVREG";
102 case ILL_COPROC: return "ILL_COPROC";
103 case ILL_BADSTK: return "ILL_BADSTK";
104 }
105 break;
106 case SIGBUS:
107 switch (code) {
108 case BUS_ADRALN: return "BUS_ADRALN";
109 case BUS_ADRERR: return "BUS_ADRERR";
110 case BUS_OBJERR: return "BUS_OBJERR";
111 }
112 break;
113 case SIGFPE:
114 switch (code) {
115 case FPE_INTDIV: return "FPE_INTDIV";
116 case FPE_INTOVF: return "FPE_INTOVF";
117 case FPE_FLTDIV: return "FPE_FLTDIV";
118 case FPE_FLTOVF: return "FPE_FLTOVF";
119 case FPE_FLTUND: return "FPE_FLTUND";
120 case FPE_FLTRES: return "FPE_FLTRES";
121 case FPE_FLTINV: return "FPE_FLTINV";
122 case FPE_FLTSUB: return "FPE_FLTSUB";
123 }
124 break;
125 case SIGSEGV:
126 switch (code) {
127 case SEGV_MAPERR: return "SEGV_MAPERR";
128 case SEGV_ACCERR: return "SEGV_ACCERR";
129 }
130 break;
Elliott Hughes8f7d4432012-12-10 10:29:05 -0800131 case SIGTRAP:
132 switch (code) {
133 case TRAP_BRKPT: return "TRAP_BRKPT";
134 case TRAP_TRACE: return "TRAP_TRACE";
135 }
136 break;
Jeff Brown053b8652012-06-06 16:25:03 -0700137 }
Elliott Hughes8f7d4432012-12-10 10:29:05 -0800138 // Then the other codes...
139 switch (code) {
140 case SI_USER: return "SI_USER";
141#if defined(SI_KERNEL)
142 case SI_KERNEL: return "SI_KERNEL";
143#endif
144 case SI_QUEUE: return "SI_QUEUE";
145 case SI_TIMER: return "SI_TIMER";
146 case SI_MESGQ: return "SI_MESGQ";
147 case SI_ASYNCIO: return "SI_ASYNCIO";
148#if defined(SI_SIGIO)
149 case SI_SIGIO: return "SI_SIGIO";
150#endif
151#if defined(SI_TKILL)
152 case SI_TKILL: return "SI_TKILL";
153#endif
154 }
155 // Then give up...
Jeff Brown053b8652012-06-06 16:25:03 -0700156 return "?";
157}
158
Ben Chengd7760c12012-09-19 16:04:01 -0700159static void dump_revision_info(log_t* log)
160{
161 char revision[PROPERTY_VALUE_MAX];
162
163 property_get("ro.revision", revision, "unknown");
164
Christopher Tate7716aef2013-04-02 14:00:27 -0700165 _LOG(log, SCOPE_AT_FAULT, "Revision: '%s'\n", revision);
Ben Chengd7760c12012-09-19 16:04:01 -0700166}
167
Jeff Brown053b8652012-06-06 16:25:03 -0700168static void dump_build_info(log_t* log)
169{
170 char fingerprint[PROPERTY_VALUE_MAX];
171
172 property_get("ro.build.fingerprint", fingerprint, "unknown");
173
Christopher Tate7716aef2013-04-02 14:00:27 -0700174 _LOG(log, SCOPE_AT_FAULT, "Build fingerprint: '%s'\n", fingerprint);
Jeff Brown053b8652012-06-06 16:25:03 -0700175}
176
177static void dump_fault_addr(log_t* log, pid_t tid, int sig)
178{
179 siginfo_t si;
180
181 memset(&si, 0, sizeof(si));
Christopher Tate7716aef2013-04-02 14:00:27 -0700182 if(ptrace(PTRACE_GETSIGINFO, tid, 0, &si)){
183 _LOG(log, SCOPE_AT_FAULT, "cannot get siginfo: %s\n", strerror(errno));
Jeff Brown053b8652012-06-06 16:25:03 -0700184 } else if (signal_has_address(sig)) {
Christopher Tate7716aef2013-04-02 14:00:27 -0700185 _LOG(log, SCOPE_AT_FAULT, "signal %d (%s), code %d (%s), fault addr %08x\n",
Jeff Brown053b8652012-06-06 16:25:03 -0700186 sig, get_signame(sig),
187 si.si_code, get_sigcode(sig, si.si_code),
188 (uintptr_t) si.si_addr);
189 } else {
Christopher Tate7716aef2013-04-02 14:00:27 -0700190 _LOG(log, SCOPE_AT_FAULT, "signal %d (%s), code %d (%s), fault addr --------\n",
Jeff Brown053b8652012-06-06 16:25:03 -0700191 sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code));
192 }
193}
194
195static void dump_thread_info(log_t* log, pid_t pid, pid_t tid, bool at_fault) {
196 char path[64];
197 char threadnamebuf[1024];
198 char* threadname = NULL;
199 FILE *fp;
200
201 snprintf(path, sizeof(path), "/proc/%d/comm", tid);
202 if ((fp = fopen(path, "r"))) {
203 threadname = fgets(threadnamebuf, sizeof(threadnamebuf), fp);
204 fclose(fp);
205 if (threadname) {
206 size_t len = strlen(threadname);
207 if (len && threadname[len - 1] == '\n') {
208 threadname[len - 1] = '\0';
209 }
210 }
211 }
212
213 if (at_fault) {
214 char procnamebuf[1024];
215 char* procname = NULL;
216
217 snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
218 if ((fp = fopen(path, "r"))) {
219 procname = fgets(procnamebuf, sizeof(procnamebuf), fp);
220 fclose(fp);
221 }
222
Christopher Tate7716aef2013-04-02 14:00:27 -0700223 _LOG(log, SCOPE_AT_FAULT, "pid: %d, tid: %d, name: %s >>> %s <<<\n", pid, tid,
Jeff Brown053b8652012-06-06 16:25:03 -0700224 threadname ? threadname : "UNKNOWN",
225 procname ? procname : "UNKNOWN");
226 } else {
Christopher Tate7716aef2013-04-02 14:00:27 -0700227 _LOG(log, 0, "pid: %d, tid: %d, name: %s\n",
228 pid, tid, threadname ? threadname : "UNKNOWN");
Jeff Brown053b8652012-06-06 16:25:03 -0700229 }
230}
231
232static void dump_backtrace(const ptrace_context_t* context __attribute((unused)),
233 log_t* log, pid_t tid __attribute((unused)), bool at_fault,
234 const backtrace_frame_t* backtrace, size_t frames) {
Christopher Tate7716aef2013-04-02 14:00:27 -0700235 int scopeFlags = at_fault ? SCOPE_AT_FAULT : 0;
236 _LOG(log, scopeFlags, "\nbacktrace:\n");
Jeff Brown053b8652012-06-06 16:25:03 -0700237
238 backtrace_symbol_t backtrace_symbols[STACK_DEPTH];
239 get_backtrace_symbols_ptrace(context, backtrace, frames, backtrace_symbols);
240 for (size_t i = 0; i < frames; i++) {
241 char line[MAX_BACKTRACE_LINE_LENGTH];
242 format_backtrace_line(i, &backtrace[i], &backtrace_symbols[i],
243 line, MAX_BACKTRACE_LINE_LENGTH);
Christopher Tate7716aef2013-04-02 14:00:27 -0700244 _LOG(log, scopeFlags, " %s\n", line);
Jeff Brown053b8652012-06-06 16:25:03 -0700245 }
246 free_backtrace_symbols(backtrace_symbols, frames);
247}
248
249static void dump_stack_segment(const ptrace_context_t* context, log_t* log, pid_t tid,
Christopher Tate7716aef2013-04-02 14:00:27 -0700250 int scopeFlags, uintptr_t* sp, size_t words, int label) {
Jeff Brown053b8652012-06-06 16:25:03 -0700251 for (size_t i = 0; i < words; i++) {
252 uint32_t stack_content;
253 if (!try_get_word_ptrace(tid, *sp, &stack_content)) {
254 break;
255 }
256
257 const map_info_t* mi;
258 const symbol_t* symbol;
259 find_symbol_ptrace(context, stack_content, &mi, &symbol);
260
261 if (symbol) {
Josh Gaoa1836542016-03-21 18:32:17 -0700262 const char* symbol_name = symbol->name;
Jeff Brown053b8652012-06-06 16:25:03 -0700263 uint32_t offset = stack_content - (mi->start + symbol->start);
264 if (!i && label >= 0) {
265 if (offset) {
Christopher Tate7716aef2013-04-02 14:00:27 -0700266 _LOG(log, scopeFlags, " #%02d %08x %08x %s (%s+%u)\n",
Jeff Brown053b8652012-06-06 16:25:03 -0700267 label, *sp, stack_content, mi ? mi->name : "", symbol_name, offset);
268 } else {
Christopher Tate7716aef2013-04-02 14:00:27 -0700269 _LOG(log, scopeFlags, " #%02d %08x %08x %s (%s)\n",
Jeff Brown053b8652012-06-06 16:25:03 -0700270 label, *sp, stack_content, mi ? mi->name : "", symbol_name);
271 }
272 } else {
273 if (offset) {
Christopher Tate7716aef2013-04-02 14:00:27 -0700274 _LOG(log, scopeFlags, " %08x %08x %s (%s+%u)\n",
Jeff Brown053b8652012-06-06 16:25:03 -0700275 *sp, stack_content, mi ? mi->name : "", symbol_name, offset);
276 } else {
Christopher Tate7716aef2013-04-02 14:00:27 -0700277 _LOG(log, scopeFlags, " %08x %08x %s (%s)\n",
Jeff Brown053b8652012-06-06 16:25:03 -0700278 *sp, stack_content, mi ? mi->name : "", symbol_name);
279 }
280 }
Jeff Brown053b8652012-06-06 16:25:03 -0700281 } else {
282 if (!i && label >= 0) {
Christopher Tate7716aef2013-04-02 14:00:27 -0700283 _LOG(log, scopeFlags, " #%02d %08x %08x %s\n",
Jeff Brown053b8652012-06-06 16:25:03 -0700284 label, *sp, stack_content, mi ? mi->name : "");
285 } else {
Christopher Tate7716aef2013-04-02 14:00:27 -0700286 _LOG(log, scopeFlags, " %08x %08x %s\n",
Jeff Brown053b8652012-06-06 16:25:03 -0700287 *sp, stack_content, mi ? mi->name : "");
288 }
289 }
290
291 *sp += sizeof(uint32_t);
292 }
293}
294
295static void dump_stack(const ptrace_context_t* context, log_t* log, pid_t tid, bool at_fault,
296 const backtrace_frame_t* backtrace, size_t frames) {
297 bool have_first = false;
298 size_t first, last;
299 for (size_t i = 0; i < frames; i++) {
300 if (backtrace[i].stack_top) {
301 if (!have_first) {
302 have_first = true;
303 first = i;
304 }
305 last = i;
306 }
307 }
308 if (!have_first) {
309 return;
310 }
311
Christopher Tate7716aef2013-04-02 14:00:27 -0700312 int scopeFlags = SCOPE_SENSITIVE | (at_fault ? SCOPE_AT_FAULT : 0);
313 _LOG(log, scopeFlags, "\nstack:\n");
Jeff Brown053b8652012-06-06 16:25:03 -0700314
315 // Dump a few words before the first frame.
Jeff Brown053b8652012-06-06 16:25:03 -0700316 uintptr_t sp = backtrace[first].stack_top - STACK_WORDS * sizeof(uint32_t);
Christopher Tate7716aef2013-04-02 14:00:27 -0700317 dump_stack_segment(context, log, tid, scopeFlags, &sp, STACK_WORDS, -1);
Jeff Brown053b8652012-06-06 16:25:03 -0700318
319 // Dump a few words from all successive frames.
320 // Only log the first 3 frames, put the rest in the tombstone.
321 for (size_t i = first; i <= last; i++) {
322 const backtrace_frame_t* frame = &backtrace[i];
323 if (sp != frame->stack_top) {
Christopher Tate7716aef2013-04-02 14:00:27 -0700324 _LOG(log, scopeFlags, " ........ ........\n");
Jeff Brown053b8652012-06-06 16:25:03 -0700325 sp = frame->stack_top;
326 }
327 if (i - first == 3) {
Christopher Tate7716aef2013-04-02 14:00:27 -0700328 scopeFlags &= (~SCOPE_AT_FAULT);
Jeff Brown053b8652012-06-06 16:25:03 -0700329 }
330 if (i == last) {
Christopher Tate7716aef2013-04-02 14:00:27 -0700331 dump_stack_segment(context, log, tid, scopeFlags, &sp, STACK_WORDS, i);
Jeff Brown053b8652012-06-06 16:25:03 -0700332 if (sp < frame->stack_top + frame->stack_size) {
Christopher Tate7716aef2013-04-02 14:00:27 -0700333 _LOG(log, scopeFlags, " ........ ........\n");
Jeff Brown053b8652012-06-06 16:25:03 -0700334 }
335 } else {
336 size_t words = frame->stack_size / sizeof(uint32_t);
337 if (words == 0) {
338 words = 1;
339 } else if (words > STACK_WORDS) {
340 words = STACK_WORDS;
341 }
Christopher Tate7716aef2013-04-02 14:00:27 -0700342 dump_stack_segment(context, log, tid, scopeFlags, &sp, words, i);
Jeff Brown053b8652012-06-06 16:25:03 -0700343 }
344 }
345}
346
347static void dump_backtrace_and_stack(const ptrace_context_t* context, log_t* log, pid_t tid,
348 bool at_fault) {
349 backtrace_frame_t backtrace[STACK_DEPTH];
350 ssize_t frames = unwind_backtrace_ptrace(tid, context, backtrace, 0, STACK_DEPTH);
351 if (frames > 0) {
352 dump_backtrace(context, log, tid, at_fault, backtrace, frames);
353 dump_stack(context, log, tid, at_fault, backtrace, frames);
354 }
355}
356
Christopher Tate300fd6f2013-04-18 14:05:52 -0700357static void dump_map(log_t* log, map_info_t* m, const char* what, int scopeFlags) {
Elliott Hughesd1420be2013-01-03 13:39:57 -0800358 if (m != NULL) {
Christopher Tate300fd6f2013-04-18 14:05:52 -0700359 _LOG(log, scopeFlags, " %08x-%08x %c%c%c %s\n", m->start, m->end,
Elliott Hughesd1420be2013-01-03 13:39:57 -0800360 m->is_readable ? 'r' : '-',
361 m->is_writable ? 'w' : '-',
362 m->is_executable ? 'x' : '-',
363 m->name);
364 } else {
Christopher Tate300fd6f2013-04-18 14:05:52 -0700365 _LOG(log, scopeFlags, " (no %s)\n", what);
Elliott Hughesd1420be2013-01-03 13:39:57 -0800366 }
367}
368
Christopher Tate300fd6f2013-04-18 14:05:52 -0700369static void dump_nearby_maps(const ptrace_context_t* context, log_t* log, pid_t tid, bool at_fault) {
370 int scopeFlags = SCOPE_SENSITIVE | (at_fault ? SCOPE_AT_FAULT : 0);
Jeff Brown053b8652012-06-06 16:25:03 -0700371 siginfo_t si;
372 memset(&si, 0, sizeof(si));
373 if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si)) {
Christopher Tate300fd6f2013-04-18 14:05:52 -0700374 _LOG(log, scopeFlags, "cannot get siginfo for %d: %s\n",
Jeff Brown053b8652012-06-06 16:25:03 -0700375 tid, strerror(errno));
376 return;
377 }
378 if (!signal_has_address(si.si_signo)) {
379 return;
380 }
381
382 uintptr_t addr = (uintptr_t) si.si_addr;
383 addr &= ~0xfff; /* round to 4K page boundary */
384 if (addr == 0) { /* null-pointer deref */
385 return;
386 }
387
Christopher Tate300fd6f2013-04-18 14:05:52 -0700388 _LOG(log, scopeFlags, "\nmemory map around fault addr %08x:\n", (int)si.si_addr);
Jeff Brown053b8652012-06-06 16:25:03 -0700389
390 /*
391 * Search for a match, or for a hole where the match would be. The list
392 * is backward from the file content, so it starts at high addresses.
393 */
Jeff Brown053b8652012-06-06 16:25:03 -0700394 map_info_t* map = context->map_info_list;
395 map_info_t *next = NULL;
396 map_info_t *prev = NULL;
397 while (map != NULL) {
398 if (addr >= map->start && addr < map->end) {
Jeff Brown053b8652012-06-06 16:25:03 -0700399 next = map->next;
400 break;
401 } else if (addr >= map->end) {
402 /* map would be between "prev" and this entry */
403 next = map;
404 map = NULL;
405 break;
406 }
407
408 prev = map;
409 map = map->next;
410 }
411
412 /*
413 * Show "next" then "match" then "prev" so that the addresses appear in
414 * ascending order (like /proc/pid/maps).
415 */
Christopher Tate300fd6f2013-04-18 14:05:52 -0700416 dump_map(log, next, "map below", scopeFlags);
417 dump_map(log, map, "map for address", scopeFlags);
418 dump_map(log, prev, "map above", scopeFlags);
Jeff Brown053b8652012-06-06 16:25:03 -0700419}
420
421static void dump_thread(const ptrace_context_t* context, log_t* log, pid_t tid, bool at_fault,
422 int* total_sleep_time_usec) {
423 wait_for_stop(tid, total_sleep_time_usec);
424
425 dump_registers(context, log, tid, at_fault);
426 dump_backtrace_and_stack(context, log, tid, at_fault);
427 if (at_fault) {
428 dump_memory_and_code(context, log, tid, at_fault);
Christopher Tate300fd6f2013-04-18 14:05:52 -0700429 dump_nearby_maps(context, log, tid, at_fault);
Jeff Brown053b8652012-06-06 16:25:03 -0700430 }
431}
432
433/* Return true if some thread is not detached cleanly */
434static bool dump_sibling_thread_report(const ptrace_context_t* context,
435 log_t* log, pid_t pid, pid_t tid, int* total_sleep_time_usec) {
436 char task_path[64];
437 snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid);
438
439 DIR* d = opendir(task_path);
440 /* Bail early if cannot open the task directory */
441 if (d == NULL) {
442 XLOG("Cannot open /proc/%d/task\n", pid);
443 return false;
444 }
445
446 bool detach_failed = false;
Elliott Hughesc463d2c2012-10-26 16:47:09 -0700447 struct dirent* de;
448 while ((de = readdir(d)) != NULL) {
Jeff Brown053b8652012-06-06 16:25:03 -0700449 /* Ignore "." and ".." */
450 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
451 continue;
452 }
453
454 /* The main thread at fault has been handled individually */
455 char* end;
456 pid_t new_tid = strtoul(de->d_name, &end, 10);
457 if (*end || new_tid == tid) {
458 continue;
459 }
460
461 /* Skip this thread if cannot ptrace it */
462 if (ptrace(PTRACE_ATTACH, new_tid, 0, 0) < 0) {
463 continue;
464 }
465
Christopher Tate7716aef2013-04-02 14:00:27 -0700466 _LOG(log, 0, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n");
Jeff Brown053b8652012-06-06 16:25:03 -0700467 dump_thread_info(log, pid, new_tid, false);
468 dump_thread(context, log, new_tid, false, total_sleep_time_usec);
469
470 if (ptrace(PTRACE_DETACH, new_tid, 0, 0) != 0) {
471 LOG("ptrace detach from %d failed: %s\n", new_tid, strerror(errno));
472 detach_failed = true;
473 }
474 }
475
476 closedir(d);
477 return detach_failed;
478}
479
480/*
481 * Reads the contents of the specified log device, filters out the entries
482 * that don't match the specified pid, and writes them to the tombstone file.
483 *
484 * If "tailOnly" is set, we only print the last few lines.
485 */
486static void dump_log_file(log_t* log, pid_t pid, const char* filename,
487 bool tailOnly)
488{
489 bool first = true;
490
491 /* circular buffer, for "tailOnly" mode */
492 const int kShortLogMaxLines = 5;
493 const int kShortLogLineLen = 256;
494 char shortLog[kShortLogMaxLines][kShortLogLineLen];
495 int shortLogCount = 0;
496 int shortLogNext = 0;
497
498 int logfd = open(filename, O_RDONLY | O_NONBLOCK);
499 if (logfd < 0) {
500 XLOG("Unable to open %s: %s\n", filename, strerror(errno));
501 return;
502 }
503
504 union {
505 unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1];
506 struct logger_entry entry;
507 } log_entry;
508
509 while (true) {
510 ssize_t actual = read(logfd, log_entry.buf, LOGGER_ENTRY_MAX_LEN);
511 if (actual < 0) {
512 if (errno == EINTR) {
513 /* interrupted by signal, retry */
514 continue;
515 } else if (errno == EAGAIN) {
516 /* non-blocking EOF; we're done */
517 break;
518 } else {
Christopher Tate7716aef2013-04-02 14:00:27 -0700519 _LOG(log, 0, "Error while reading log: %s\n",
Jeff Brown053b8652012-06-06 16:25:03 -0700520 strerror(errno));
521 break;
522 }
523 } else if (actual == 0) {
Christopher Tate7716aef2013-04-02 14:00:27 -0700524 _LOG(log, 0, "Got zero bytes while reading log: %s\n",
Jeff Brown053b8652012-06-06 16:25:03 -0700525 strerror(errno));
526 break;
527 }
528
529 /*
530 * NOTE: if you XLOG something here, this will spin forever,
531 * because you will be writing as fast as you're reading. Any
532 * high-frequency debug diagnostics should just be written to
533 * the tombstone file.
534 */
535
536 struct logger_entry* entry = &log_entry.entry;
537
538 if (entry->pid != (int32_t) pid) {
539 /* wrong pid, ignore */
540 continue;
541 }
542
543 if (first) {
Christopher Tate7716aef2013-04-02 14:00:27 -0700544 _LOG(log, 0, "--------- %slog %s\n",
Jeff Brown053b8652012-06-06 16:25:03 -0700545 tailOnly ? "tail end of " : "", filename);
546 first = false;
547 }
548
549 /*
550 * Msg format is: <priority:1><tag:N>\0<message:N>\0
551 *
552 * We want to display it in the same format as "logcat -v threadtime"
553 * (although in this case the pid is redundant).
554 *
555 * TODO: scan for line breaks ('\n') and display each text line
556 * on a separate line, prefixed with the header, like logcat does.
557 */
558 static const char* kPrioChars = "!.VDIWEFS";
559 unsigned char prio = entry->msg[0];
560 char* tag = entry->msg + 1;
561 char* msg = tag + strlen(tag) + 1;
562
563 /* consume any trailing newlines */
564 char* eatnl = msg + strlen(msg) - 1;
565 while (eatnl >= msg && *eatnl == '\n') {
566 *eatnl-- = '\0';
567 }
568
569 char prioChar = (prio < strlen(kPrioChars) ? kPrioChars[prio] : '?');
570
571 char timeBuf[32];
572 time_t sec = (time_t) entry->sec;
573 struct tm tmBuf;
574 struct tm* ptm;
575 ptm = localtime_r(&sec, &tmBuf);
576 strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", ptm);
577
578 if (tailOnly) {
579 snprintf(shortLog[shortLogNext], kShortLogLineLen,
580 "%s.%03d %5d %5d %c %-8s: %s",
581 timeBuf, entry->nsec / 1000000, entry->pid, entry->tid,
582 prioChar, tag, msg);
583 shortLogNext = (shortLogNext + 1) % kShortLogMaxLines;
584 shortLogCount++;
585 } else {
Christopher Tate7716aef2013-04-02 14:00:27 -0700586 _LOG(log, 0, "%s.%03d %5d %5d %c %-8s: %s\n",
Jeff Brown053b8652012-06-06 16:25:03 -0700587 timeBuf, entry->nsec / 1000000, entry->pid, entry->tid,
588 prioChar, tag, msg);
589 }
590 }
591
592 if (tailOnly) {
593 int i;
594
595 /*
596 * If we filled the buffer, we want to start at "next", which has
597 * the oldest entry. If we didn't, we want to start at zero.
598 */
599 if (shortLogCount < kShortLogMaxLines) {
600 shortLogNext = 0;
601 } else {
602 shortLogCount = kShortLogMaxLines; /* cap at window size */
603 }
604
605 for (i = 0; i < shortLogCount; i++) {
Christopher Tate7716aef2013-04-02 14:00:27 -0700606 _LOG(log, 0, "%s\n", shortLog[shortLogNext]);
Jeff Brown053b8652012-06-06 16:25:03 -0700607 shortLogNext = (shortLogNext + 1) % kShortLogMaxLines;
608 }
609 }
610
611 close(logfd);
612}
613
614/*
615 * Dumps the logs generated by the specified pid to the tombstone, from both
616 * "system" and "main" log devices. Ideally we'd interleave the output.
617 */
618static void dump_logs(log_t* log, pid_t pid, bool tailOnly)
619{
620 dump_log_file(log, pid, "/dev/log/system", tailOnly);
621 dump_log_file(log, pid, "/dev/log/main", tailOnly);
622}
623
Elliott Hughese5f8a692013-04-04 13:52:01 -0700624static void dump_abort_message(log_t* log, pid_t tid, uintptr_t address) {
625 if (address == 0) {
626 return;
627 }
628
629 address += sizeof(size_t); // Skip the buffer length.
630
631 char msg[512];
632 memset(msg, 0, sizeof(msg));
633 char* p = &msg[0];
634 while (p < &msg[sizeof(msg)]) {
635 uint32_t data;
636 if (!try_get_word_ptrace(tid, address, &data)) {
637 break;
638 }
639 address += sizeof(uint32_t);
640
641 if ((*p++ = (data >> 0) & 0xff) == 0) {
642 break;
643 }
644 if ((*p++ = (data >> 8) & 0xff) == 0) {
645 break;
646 }
647 if ((*p++ = (data >> 16) & 0xff) == 0) {
648 break;
649 }
650 if ((*p++ = (data >> 24) & 0xff) == 0) {
651 break;
652 }
653 }
654 msg[sizeof(msg) - 1] = '\0';
655
Christopher Tate7716aef2013-04-02 14:00:27 -0700656 _LOG(log, SCOPE_AT_FAULT, "Abort message: '%s'\n", msg);
Elliott Hughese5f8a692013-04-04 13:52:01 -0700657}
658
Jeff Brown053b8652012-06-06 16:25:03 -0700659/*
660 * Dumps all information about the specified pid to the tombstone.
661 */
Elliott Hughese5f8a692013-04-04 13:52:01 -0700662static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, uintptr_t abort_msg_address,
663 bool dump_sibling_threads, int* total_sleep_time_usec)
Jeff Brown053b8652012-06-06 16:25:03 -0700664{
665 /* don't copy log messages to tombstone unless this is a dev device */
666 char value[PROPERTY_VALUE_MAX];
667 property_get("ro.debuggable", value, "0");
668 bool want_logs = (value[0] == '1');
669
Christopher Tateded2e5a2013-03-19 13:12:23 -0700670 if (log->amfd >= 0) {
671 /*
672 * Activity Manager protocol: binary 32-bit network-byte-order ints for the
673 * pid and signal number, followed by the raw text of the dump, culminating
674 * in a zero byte that marks end-of-data.
675 */
676 uint32_t datum = htonl(pid);
677 TEMP_FAILURE_RETRY( write(log->amfd, &datum, 4) );
678 datum = htonl(signal);
679 TEMP_FAILURE_RETRY( write(log->amfd, &datum, 4) );
680 }
681
Christopher Tate7716aef2013-04-02 14:00:27 -0700682 _LOG(log, SCOPE_AT_FAULT,
Jeff Brown053b8652012-06-06 16:25:03 -0700683 "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n");
684 dump_build_info(log);
Ben Chengd7760c12012-09-19 16:04:01 -0700685 dump_revision_info(log);
Jeff Brown053b8652012-06-06 16:25:03 -0700686 dump_thread_info(log, pid, tid, true);
Elliott Hughese5f8a692013-04-04 13:52:01 -0700687 if (signal) {
Jeff Brown053b8652012-06-06 16:25:03 -0700688 dump_fault_addr(log, tid, signal);
689 }
Elliott Hughese5f8a692013-04-04 13:52:01 -0700690 dump_abort_message(log, tid, abort_msg_address);
Jeff Brown053b8652012-06-06 16:25:03 -0700691
692 ptrace_context_t* context = load_ptrace_context(tid);
693 dump_thread(context, log, tid, true, total_sleep_time_usec);
694
695 if (want_logs) {
696 dump_logs(log, pid, true);
697 }
698
699 bool detach_failed = false;
700 if (dump_sibling_threads) {
701 detach_failed = dump_sibling_thread_report(context, log, pid, tid, total_sleep_time_usec);
702 }
703
704 free_ptrace_context(context);
705
706 if (want_logs) {
707 dump_logs(log, pid, false);
708 }
Christopher Tateded2e5a2013-03-19 13:12:23 -0700709
710 /* send EOD to the Activity Manager, then wait for its ack to avoid racing ahead
711 * and killing the target out from under it */
712 if (log->amfd >= 0) {
713 uint8_t eodMarker = 0;
714 TEMP_FAILURE_RETRY( write(log->amfd, &eodMarker, 1) );
715 /* 3 sec timeout reading the ack; we're fine if that happens */
716 TEMP_FAILURE_RETRY( read(log->amfd, &eodMarker, 1) );
717 }
718
Jeff Brown053b8652012-06-06 16:25:03 -0700719 return detach_failed;
720}
721
722/*
723 * find_and_open_tombstone - find an available tombstone slot, if any, of the
724 * form tombstone_XX where XX is 00 to MAX_TOMBSTONES-1, inclusive. If no
725 * file is available, we reuse the least-recently-modified file.
726 *
727 * Returns the path of the tombstone file, allocated using malloc(). Caller must free() it.
728 */
729static char* find_and_open_tombstone(int* fd)
730{
731 unsigned long mtime = ULONG_MAX;
732 struct stat sb;
733
734 /*
735 * XXX: Our stat.st_mtime isn't time_t. If it changes, as it probably ought
736 * to, our logic breaks. This check will generate a warning if that happens.
737 */
738 typecheck(mtime, sb.st_mtime);
739
740 /*
741 * In a single wolf-like pass, find an available slot and, in case none
742 * exist, find and record the least-recently-modified file.
743 */
744 char path[128];
745 int oldest = 0;
746 for (int i = 0; i < MAX_TOMBSTONES; i++) {
747 snprintf(path, sizeof(path), TOMBSTONE_DIR"/tombstone_%02d", i);
748
749 if (!stat(path, &sb)) {
750 if (sb.st_mtime < mtime) {
751 oldest = i;
752 mtime = sb.st_mtime;
753 }
754 continue;
755 }
756 if (errno != ENOENT)
757 continue;
758
Josh Gao9515c232016-02-16 14:24:50 -0800759 *fd = open(path, O_CREAT | O_EXCL | O_WRONLY | O_NOFOLLOW | O_CLOEXEC, 0600);
Jeff Brown053b8652012-06-06 16:25:03 -0700760 if (*fd < 0)
761 continue; /* raced ? */
762
763 fchown(*fd, AID_SYSTEM, AID_SYSTEM);
764 return strdup(path);
765 }
766
767 /* we didn't find an available file, so we clobber the oldest one */
768 snprintf(path, sizeof(path), TOMBSTONE_DIR"/tombstone_%02d", oldest);
Josh Gao9515c232016-02-16 14:24:50 -0800769 *fd = open(path, O_CREAT | O_TRUNC | O_WRONLY | O_NOFOLLOW | O_CLOEXEC, 0600);
Jeff Brown053b8652012-06-06 16:25:03 -0700770 if (*fd < 0) {
771 LOG("failed to open tombstone file '%s': %s\n", path, strerror(errno));
772 return NULL;
773 }
774 fchown(*fd, AID_SYSTEM, AID_SYSTEM);
775 return strdup(path);
776}
777
Christopher Tateded2e5a2013-03-19 13:12:23 -0700778static int activity_manager_connect() {
779 int amfd = socket(PF_UNIX, SOCK_STREAM, 0);
780 if (amfd >= 0) {
781 struct sockaddr_un address;
782 int err;
783
784 memset(&address, 0, sizeof(address));
785 address.sun_family = AF_UNIX;
786 strncpy(address.sun_path, NCRASH_SOCKET_PATH, sizeof(address.sun_path));
787 err = TEMP_FAILURE_RETRY( connect(amfd, (struct sockaddr*) &address, sizeof(address)) );
788 if (!err) {
789 struct timeval tv;
790 memset(&tv, 0, sizeof(tv));
791 tv.tv_sec = 1; // tight leash
792 err = setsockopt(amfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
793 if (!err) {
794 tv.tv_sec = 3; // 3 seconds on handshake read
795 err = setsockopt(amfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
796 }
797 }
798 if (err) {
799 close(amfd);
800 amfd = -1;
801 }
802 }
803
804 return amfd;
805}
806
Elliott Hughese5f8a692013-04-04 13:52:01 -0700807char* engrave_tombstone(pid_t pid, pid_t tid, int signal, uintptr_t abort_msg_address,
Jeff Brown053b8652012-06-06 16:25:03 -0700808 bool dump_sibling_threads, bool quiet, bool* detach_failed,
809 int* total_sleep_time_usec) {
Jeff Brown053b8652012-06-06 16:25:03 -0700810 int fd;
811 char* path = find_and_open_tombstone(&fd);
812 if (!path) {
813 *detach_failed = false;
814 return NULL;
815 }
816
817 log_t log;
818 log.tfd = fd;
Christopher Tateded2e5a2013-03-19 13:12:23 -0700819 log.amfd = activity_manager_connect();
Jeff Brown053b8652012-06-06 16:25:03 -0700820 log.quiet = quiet;
Elliott Hughese5f8a692013-04-04 13:52:01 -0700821 *detach_failed = dump_crash(&log, pid, tid, signal, abort_msg_address, dump_sibling_threads,
Jeff Brown053b8652012-06-06 16:25:03 -0700822 total_sleep_time_usec);
823
Christopher Tateded2e5a2013-03-19 13:12:23 -0700824 close(log.amfd);
Jeff Brown053b8652012-06-06 16:25:03 -0700825 close(fd);
826 return path;
827}