1053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown/*
2053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * Copyright (C) 2012 The Android Open Source Project
3053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown *
4053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
5053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * you may not use this file except in compliance with the License.
6053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * You may obtain a copy of the License at
7053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown *
8053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
9053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown *
10053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * Unless required by applicable law or agreed to in writing, software
11053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
12053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * See the License for the specific language governing permissions and
14053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * limitations under the License.
15053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown */
16053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
17053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <stddef.h>
18053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <stdbool.h>
19053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <stdlib.h>
20053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <signal.h>
21053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <string.h>
22053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <stdio.h>
23053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <fcntl.h>
24053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <errno.h>
25053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <dirent.h>
26053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <time.h>
27053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <sys/ptrace.h>
28053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <sys/stat.h>
29053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
30053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <private/android_filesystem_config.h>
31053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
32053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <cutils/logger.h>
33053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <cutils/properties.h>
34053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
35053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <corkscrew/demangle.h>
36053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <corkscrew/backtrace.h>
37053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
38ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate#include <sys/socket.h>
39ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate#include <linux/un.h>
40ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate
41f1186f3e980f5ebcc3380d8a7f746bf8a45e3531rpcraig#include <selinux/android.h>
42f1186f3e980f5ebcc3380d8a7f746bf8a45e3531rpcraig
43053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include "machine.h"
44053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include "tombstone.h"
45053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include "utility.h"
46053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
47053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#define STACK_DEPTH 32
48053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#define STACK_WORDS 16
49053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
50053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#define MAX_TOMBSTONES  10
51053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#define TOMBSTONE_DIR   "/data/tombstones"
52053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
53ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate/* Must match the path defined in NativeCrashListener.java */
54ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate#define NCRASH_SOCKET_PATH "/data/system/ndebugsocket"
55ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate
56053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#define typecheck(x,y) {    \
57053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    typeof(x) __dummy1;     \
58053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    typeof(y) __dummy2;     \
59053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    (void)(&__dummy1 == &__dummy2); }
60053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
61053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
62053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic bool signal_has_address(int sig) {
63053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    switch (sig) {
64053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case SIGILL:
65053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case SIGFPE:
66053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case SIGSEGV:
67053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case SIGBUS:
68053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            return true;
69053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        default:
70053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            return false;
71053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
72053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
73053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
74053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic const char *get_signame(int sig)
75053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown{
76053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    switch(sig) {
77053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    case SIGILL:     return "SIGILL";
78053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    case SIGABRT:    return "SIGABRT";
79053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    case SIGBUS:     return "SIGBUS";
80053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    case SIGFPE:     return "SIGFPE";
81053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    case SIGSEGV:    return "SIGSEGV";
82053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    case SIGPIPE:    return "SIGPIPE";
83231e3c83a3a70b11160fb0da108ebf2e0e7470e2Chris Dearman#ifdef SIGSTKFLT
84053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    case SIGSTKFLT:  return "SIGSTKFLT";
85231e3c83a3a70b11160fb0da108ebf2e0e7470e2Chris Dearman#endif
86053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    case SIGSTOP:    return "SIGSTOP";
87053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    default:         return "?";
88053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
89053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
90053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
91053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic const char *get_sigcode(int signo, int code)
92053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown{
938f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes    // Try the signal-specific codes...
94053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    switch (signo) {
95053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    case SIGILL:
96053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        switch (code) {
97053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case ILL_ILLOPC: return "ILL_ILLOPC";
98053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case ILL_ILLOPN: return "ILL_ILLOPN";
99053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case ILL_ILLADR: return "ILL_ILLADR";
100053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case ILL_ILLTRP: return "ILL_ILLTRP";
101053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case ILL_PRVOPC: return "ILL_PRVOPC";
102053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case ILL_PRVREG: return "ILL_PRVREG";
103053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case ILL_COPROC: return "ILL_COPROC";
104053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case ILL_BADSTK: return "ILL_BADSTK";
105053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
106053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        break;
107053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    case SIGBUS:
108053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        switch (code) {
109053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case BUS_ADRALN: return "BUS_ADRALN";
110053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case BUS_ADRERR: return "BUS_ADRERR";
111053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case BUS_OBJERR: return "BUS_OBJERR";
112053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
113053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        break;
114053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    case SIGFPE:
115053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        switch (code) {
116053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case FPE_INTDIV: return "FPE_INTDIV";
117053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case FPE_INTOVF: return "FPE_INTOVF";
118053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case FPE_FLTDIV: return "FPE_FLTDIV";
119053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case FPE_FLTOVF: return "FPE_FLTOVF";
120053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case FPE_FLTUND: return "FPE_FLTUND";
121053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case FPE_FLTRES: return "FPE_FLTRES";
122053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case FPE_FLTINV: return "FPE_FLTINV";
123053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case FPE_FLTSUB: return "FPE_FLTSUB";
124053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
125053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        break;
126053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    case SIGSEGV:
127053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        switch (code) {
128053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case SEGV_MAPERR: return "SEGV_MAPERR";
129053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case SEGV_ACCERR: return "SEGV_ACCERR";
130053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
131053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        break;
1328f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes    case SIGTRAP:
1338f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes        switch (code) {
1348f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes        case TRAP_BRKPT: return "TRAP_BRKPT";
1358f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes        case TRAP_TRACE: return "TRAP_TRACE";
1368f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes        }
1378f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes        break;
1388f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes    }
1398f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes    // Then the other codes...
1408f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes    switch (code) {
1418f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes    case SI_USER:    return "SI_USER";
1428f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes#if defined(SI_KERNEL)
1438f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes    case SI_KERNEL:  return "SI_KERNEL";
1448f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes#endif
1458f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes    case SI_QUEUE:   return "SI_QUEUE";
1468f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes    case SI_TIMER:   return "SI_TIMER";
1478f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes    case SI_MESGQ:   return "SI_MESGQ";
1488f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes    case SI_ASYNCIO: return "SI_ASYNCIO";
1498f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes#if defined(SI_SIGIO)
1508f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes    case SI_SIGIO:   return "SI_SIGIO";
1518f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes#endif
1528f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes#if defined(SI_TKILL)
1538f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes    case SI_TKILL:   return "SI_TKILL";
1548f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes#endif
155053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
1568f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes    // Then give up...
157053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    return "?";
158053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
159053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
160d7760c1688f8276a05e33345d81639f8cb5e7c3fBen Chengstatic void dump_revision_info(log_t* log)
161d7760c1688f8276a05e33345d81639f8cb5e7c3fBen Cheng{
162d7760c1688f8276a05e33345d81639f8cb5e7c3fBen Cheng    char revision[PROPERTY_VALUE_MAX];
163d7760c1688f8276a05e33345d81639f8cb5e7c3fBen Cheng
164d7760c1688f8276a05e33345d81639f8cb5e7c3fBen Cheng    property_get("ro.revision", revision, "unknown");
165d7760c1688f8276a05e33345d81639f8cb5e7c3fBen Cheng
1667716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate    _LOG(log, SCOPE_AT_FAULT, "Revision: '%s'\n", revision);
167d7760c1688f8276a05e33345d81639f8cb5e7c3fBen Cheng}
168d7760c1688f8276a05e33345d81639f8cb5e7c3fBen Cheng
169053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic void dump_build_info(log_t* log)
170053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown{
171053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    char fingerprint[PROPERTY_VALUE_MAX];
172053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
173053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    property_get("ro.build.fingerprint", fingerprint, "unknown");
174053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
1757716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate    _LOG(log, SCOPE_AT_FAULT, "Build fingerprint: '%s'\n", fingerprint);
176053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
177053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
178053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic void dump_fault_addr(log_t* log, pid_t tid, int sig)
179053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown{
180053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    siginfo_t si;
181053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
182053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    memset(&si, 0, sizeof(si));
1837716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate    if(ptrace(PTRACE_GETSIGINFO, tid, 0, &si)){
1847716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate        _LOG(log, SCOPE_AT_FAULT, "cannot get siginfo: %s\n", strerror(errno));
185053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    } else if (signal_has_address(sig)) {
1867716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate        _LOG(log, SCOPE_AT_FAULT, "signal %d (%s), code %d (%s), fault addr %08x\n",
187053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown             sig, get_signame(sig),
188053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown             si.si_code, get_sigcode(sig, si.si_code),
189053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown             (uintptr_t) si.si_addr);
190053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    } else {
1917716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate        _LOG(log, SCOPE_AT_FAULT, "signal %d (%s), code %d (%s), fault addr --------\n",
192053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown             sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code));
193053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
194053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
195053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
196053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic void dump_thread_info(log_t* log, pid_t pid, pid_t tid, bool at_fault) {
197053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    char path[64];
198053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    char threadnamebuf[1024];
199053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    char* threadname = NULL;
200053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    FILE *fp;
201053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
202053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    snprintf(path, sizeof(path), "/proc/%d/comm", tid);
203053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    if ((fp = fopen(path, "r"))) {
204053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        threadname = fgets(threadnamebuf, sizeof(threadnamebuf), fp);
205053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        fclose(fp);
206053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        if (threadname) {
207053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            size_t len = strlen(threadname);
208053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            if (len && threadname[len - 1] == '\n') {
209053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                threadname[len - 1] = '\0';
210053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            }
211053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
212053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
213053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
214053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    if (at_fault) {
215053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        char procnamebuf[1024];
216053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        char* procname = NULL;
217053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
218053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
219053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        if ((fp = fopen(path, "r"))) {
220053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            procname = fgets(procnamebuf, sizeof(procnamebuf), fp);
221053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            fclose(fp);
222053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
223053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
2247716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate        _LOG(log, SCOPE_AT_FAULT, "pid: %d, tid: %d, name: %s  >>> %s <<<\n", pid, tid,
225053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                threadname ? threadname : "UNKNOWN",
226053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                procname ? procname : "UNKNOWN");
227053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    } else {
2287716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate        _LOG(log, 0, "pid: %d, tid: %d, name: %s\n",
2297716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate                pid, tid, threadname ? threadname : "UNKNOWN");
230053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
231053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
232053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
233053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic void dump_backtrace(const ptrace_context_t* context __attribute((unused)),
234053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        log_t* log, pid_t tid __attribute((unused)), bool at_fault,
235053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        const backtrace_frame_t* backtrace, size_t frames) {
2367716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate    int scopeFlags = at_fault ? SCOPE_AT_FAULT : 0;
2377716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate    _LOG(log, scopeFlags, "\nbacktrace:\n");
238053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
239053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    backtrace_symbol_t backtrace_symbols[STACK_DEPTH];
240053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    get_backtrace_symbols_ptrace(context, backtrace, frames, backtrace_symbols);
241053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    for (size_t i = 0; i < frames; i++) {
242053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        char line[MAX_BACKTRACE_LINE_LENGTH];
243053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        format_backtrace_line(i, &backtrace[i], &backtrace_symbols[i],
244053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                line, MAX_BACKTRACE_LINE_LENGTH);
2457716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate        _LOG(log, scopeFlags, "    %s\n", line);
246053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
247053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    free_backtrace_symbols(backtrace_symbols, frames);
248053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
249053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
250053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic void dump_stack_segment(const ptrace_context_t* context, log_t* log, pid_t tid,
2517716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate        int scopeFlags, uintptr_t* sp, size_t words, int label) {
252053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    for (size_t i = 0; i < words; i++) {
253053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        uint32_t stack_content;
254053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        if (!try_get_word_ptrace(tid, *sp, &stack_content)) {
255053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            break;
256053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
257053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
258053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        const map_info_t* mi;
259053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        const symbol_t* symbol;
260053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        find_symbol_ptrace(context, stack_content, &mi, &symbol);
261053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
262053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        if (symbol) {
263053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            char* demangled_name = demangle_symbol_name(symbol->name);
264053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            const char* symbol_name = demangled_name ? demangled_name : symbol->name;
265053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            uint32_t offset = stack_content - (mi->start + symbol->start);
266053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            if (!i && label >= 0) {
267053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                if (offset) {
2687716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate                    _LOG(log, scopeFlags, "    #%02d  %08x  %08x  %s (%s+%u)\n",
269053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                            label, *sp, stack_content, mi ? mi->name : "", symbol_name, offset);
270053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                } else {
2717716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate                    _LOG(log, scopeFlags, "    #%02d  %08x  %08x  %s (%s)\n",
272053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                            label, *sp, stack_content, mi ? mi->name : "", symbol_name);
273053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                }
274053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            } else {
275053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                if (offset) {
2767716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate                    _LOG(log, scopeFlags, "         %08x  %08x  %s (%s+%u)\n",
277053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                            *sp, stack_content, mi ? mi->name : "", symbol_name, offset);
278053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                } else {
2797716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate                    _LOG(log, scopeFlags, "         %08x  %08x  %s (%s)\n",
280053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                            *sp, stack_content, mi ? mi->name : "", symbol_name);
281053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                }
282053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            }
283053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            free(demangled_name);
284053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        } else {
285053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            if (!i && label >= 0) {
2867716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate                _LOG(log, scopeFlags, "    #%02d  %08x  %08x  %s\n",
287053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                        label, *sp, stack_content, mi ? mi->name : "");
288053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            } else {
2897716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate                _LOG(log, scopeFlags, "         %08x  %08x  %s\n",
290053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                        *sp, stack_content, mi ? mi->name : "");
291053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            }
292053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
293053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
294053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        *sp += sizeof(uint32_t);
295053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
296053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
297053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
298053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic void dump_stack(const ptrace_context_t* context, log_t* log, pid_t tid, bool at_fault,
299053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        const backtrace_frame_t* backtrace, size_t frames) {
300053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    bool have_first = false;
301053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    size_t first, last;
302053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    for (size_t i = 0; i < frames; i++) {
303053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        if (backtrace[i].stack_top) {
304053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            if (!have_first) {
305053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                have_first = true;
306053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                first = i;
307053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            }
308053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            last = i;
309053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
310053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
311053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    if (!have_first) {
312053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        return;
313053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
314053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
3157716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate    int scopeFlags = SCOPE_SENSITIVE | (at_fault ? SCOPE_AT_FAULT : 0);
3167716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate    _LOG(log, scopeFlags, "\nstack:\n");
317053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
318053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    // Dump a few words before the first frame.
319053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    uintptr_t sp = backtrace[first].stack_top - STACK_WORDS * sizeof(uint32_t);
3207716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate    dump_stack_segment(context, log, tid, scopeFlags, &sp, STACK_WORDS, -1);
321053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
322053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    // Dump a few words from all successive frames.
323053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    // Only log the first 3 frames, put the rest in the tombstone.
324053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    for (size_t i = first; i <= last; i++) {
325053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        const backtrace_frame_t* frame = &backtrace[i];
326053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        if (sp != frame->stack_top) {
3277716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate            _LOG(log, scopeFlags, "         ........  ........\n");
328053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            sp = frame->stack_top;
329053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
330053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        if (i - first == 3) {
3317716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate            scopeFlags &= (~SCOPE_AT_FAULT);
332053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
333053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        if (i == last) {
3347716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate            dump_stack_segment(context, log, tid, scopeFlags, &sp, STACK_WORDS, i);
335053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            if (sp < frame->stack_top + frame->stack_size) {
3367716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate                _LOG(log, scopeFlags, "         ........  ........\n");
337053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            }
338053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        } else {
339053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            size_t words = frame->stack_size / sizeof(uint32_t);
340053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            if (words == 0) {
341053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                words = 1;
342053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            } else if (words > STACK_WORDS) {
343053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                words = STACK_WORDS;
344053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            }
3457716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate            dump_stack_segment(context, log, tid, scopeFlags, &sp, words, i);
346053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
347053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
348053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
349053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
350053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic void dump_backtrace_and_stack(const ptrace_context_t* context, log_t* log, pid_t tid,
351053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        bool at_fault) {
352053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    backtrace_frame_t backtrace[STACK_DEPTH];
353053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    ssize_t frames = unwind_backtrace_ptrace(tid, context, backtrace, 0, STACK_DEPTH);
354053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    if (frames > 0) {
355053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        dump_backtrace(context, log, tid, at_fault, backtrace, frames);
356053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        dump_stack(context, log, tid, at_fault, backtrace, frames);
357053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
358053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
359053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
360300fd6fdbc19bbb64a13b0a9d0ea7d284a831e33Christopher Tatestatic void dump_map(log_t* log, map_info_t* m, const char* what, int scopeFlags) {
361d1420be6133fc5ba71d59315936fb85239ea78b1Elliott Hughes    if (m != NULL) {
362300fd6fdbc19bbb64a13b0a9d0ea7d284a831e33Christopher Tate        _LOG(log, scopeFlags, "    %08x-%08x %c%c%c %s\n", m->start, m->end,
363d1420be6133fc5ba71d59315936fb85239ea78b1Elliott Hughes             m->is_readable ? 'r' : '-',
364d1420be6133fc5ba71d59315936fb85239ea78b1Elliott Hughes             m->is_writable ? 'w' : '-',
365d1420be6133fc5ba71d59315936fb85239ea78b1Elliott Hughes             m->is_executable ? 'x' : '-',
366d1420be6133fc5ba71d59315936fb85239ea78b1Elliott Hughes             m->name);
367d1420be6133fc5ba71d59315936fb85239ea78b1Elliott Hughes    } else {
368300fd6fdbc19bbb64a13b0a9d0ea7d284a831e33Christopher Tate        _LOG(log, scopeFlags, "    (no %s)\n", what);
369d1420be6133fc5ba71d59315936fb85239ea78b1Elliott Hughes    }
370d1420be6133fc5ba71d59315936fb85239ea78b1Elliott Hughes}
371d1420be6133fc5ba71d59315936fb85239ea78b1Elliott Hughes
372300fd6fdbc19bbb64a13b0a9d0ea7d284a831e33Christopher Tatestatic void dump_nearby_maps(const ptrace_context_t* context, log_t* log, pid_t tid, bool at_fault) {
373300fd6fdbc19bbb64a13b0a9d0ea7d284a831e33Christopher Tate    int scopeFlags = SCOPE_SENSITIVE | (at_fault ? SCOPE_AT_FAULT : 0);
374053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    siginfo_t si;
375053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    memset(&si, 0, sizeof(si));
376053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si)) {
377300fd6fdbc19bbb64a13b0a9d0ea7d284a831e33Christopher Tate        _LOG(log, scopeFlags, "cannot get siginfo for %d: %s\n",
378053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                tid, strerror(errno));
379053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        return;
380053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
381053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    if (!signal_has_address(si.si_signo)) {
382053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        return;
383053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
384053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
385053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    uintptr_t addr = (uintptr_t) si.si_addr;
386053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    addr &= ~0xfff;     /* round to 4K page boundary */
387053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    if (addr == 0) {    /* null-pointer deref */
388053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        return;
389053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
390053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
391300fd6fdbc19bbb64a13b0a9d0ea7d284a831e33Christopher Tate    _LOG(log, scopeFlags, "\nmemory map around fault addr %08x:\n", (int)si.si_addr);
392053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
393053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    /*
394053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown     * Search for a match, or for a hole where the match would be.  The list
395053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown     * is backward from the file content, so it starts at high addresses.
396053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown     */
397053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    map_info_t* map = context->map_info_list;
398053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    map_info_t *next = NULL;
399053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    map_info_t *prev = NULL;
400053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    while (map != NULL) {
401053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        if (addr >= map->start && addr < map->end) {
402053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            next = map->next;
403053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            break;
404053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        } else if (addr >= map->end) {
405053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            /* map would be between "prev" and this entry */
406053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            next = map;
407053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            map = NULL;
408053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            break;
409053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
410053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
411053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        prev = map;
412053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        map = map->next;
413053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
414053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
415053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    /*
416053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown     * Show "next" then "match" then "prev" so that the addresses appear in
417053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown     * ascending order (like /proc/pid/maps).
418053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown     */
419300fd6fdbc19bbb64a13b0a9d0ea7d284a831e33Christopher Tate    dump_map(log, next, "map below", scopeFlags);
420300fd6fdbc19bbb64a13b0a9d0ea7d284a831e33Christopher Tate    dump_map(log, map, "map for address", scopeFlags);
421300fd6fdbc19bbb64a13b0a9d0ea7d284a831e33Christopher Tate    dump_map(log, prev, "map above", scopeFlags);
422053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
423053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
424053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic void dump_thread(const ptrace_context_t* context, log_t* log, pid_t tid, bool at_fault,
425053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        int* total_sleep_time_usec) {
426053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    wait_for_stop(tid, total_sleep_time_usec);
427053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
428053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    dump_registers(context, log, tid, at_fault);
429053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    dump_backtrace_and_stack(context, log, tid, at_fault);
430053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    if (at_fault) {
431053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        dump_memory_and_code(context, log, tid, at_fault);
432300fd6fdbc19bbb64a13b0a9d0ea7d284a831e33Christopher Tate        dump_nearby_maps(context, log, tid, at_fault);
433053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
434053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
435053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
436053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown/* Return true if some thread is not detached cleanly */
437053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic bool dump_sibling_thread_report(const ptrace_context_t* context,
438053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        log_t* log, pid_t pid, pid_t tid, int* total_sleep_time_usec) {
439053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    char task_path[64];
440053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid);
441053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
442053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    DIR* d = opendir(task_path);
443053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    /* Bail early if cannot open the task directory */
444053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    if (d == NULL) {
445053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        XLOG("Cannot open /proc/%d/task\n", pid);
446053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        return false;
447053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
448053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
449053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    bool detach_failed = false;
450c463d2cf9c5717dcd37589deb01615b984266c8cElliott Hughes    struct dirent* de;
451c463d2cf9c5717dcd37589deb01615b984266c8cElliott Hughes    while ((de = readdir(d)) != NULL) {
452053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        /* Ignore "." and ".." */
453053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
454053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            continue;
455053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
456053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
457053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        /* The main thread at fault has been handled individually */
458053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        char* end;
459053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        pid_t new_tid = strtoul(de->d_name, &end, 10);
460053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        if (*end || new_tid == tid) {
461053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            continue;
462053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
463053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
464053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        /* Skip this thread if cannot ptrace it */
465053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        if (ptrace(PTRACE_ATTACH, new_tid, 0, 0) < 0) {
466053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            continue;
467053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
468053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
4697716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate        _LOG(log, 0, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n");
470053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        dump_thread_info(log, pid, new_tid, false);
471053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        dump_thread(context, log, new_tid, false, total_sleep_time_usec);
472053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
473053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        if (ptrace(PTRACE_DETACH, new_tid, 0, 0) != 0) {
474053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            LOG("ptrace detach from %d failed: %s\n", new_tid, strerror(errno));
475053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            detach_failed = true;
476053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
477053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
478053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
479053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    closedir(d);
480053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    return detach_failed;
481053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
482053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
483053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown/*
484053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * Reads the contents of the specified log device, filters out the entries
485053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * that don't match the specified pid, and writes them to the tombstone file.
486053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown *
487053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * If "tailOnly" is set, we only print the last few lines.
488053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown */
489053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic void dump_log_file(log_t* log, pid_t pid, const char* filename,
490053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    bool tailOnly)
491053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown{
492053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    bool first = true;
493053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
494053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    /* circular buffer, for "tailOnly" mode */
495053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    const int kShortLogMaxLines = 5;
496053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    const int kShortLogLineLen = 256;
497053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    char shortLog[kShortLogMaxLines][kShortLogLineLen];
498053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    int shortLogCount = 0;
499053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    int shortLogNext = 0;
500053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
501053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    int logfd = open(filename, O_RDONLY | O_NONBLOCK);
502053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    if (logfd < 0) {
503053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        XLOG("Unable to open %s: %s\n", filename, strerror(errno));
504053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        return;
505053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
506053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
507053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    union {
508053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1];
509053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        struct logger_entry entry;
510053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    } log_entry;
511053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
512053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    while (true) {
513053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        ssize_t actual = read(logfd, log_entry.buf, LOGGER_ENTRY_MAX_LEN);
514053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        if (actual < 0) {
515053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            if (errno == EINTR) {
516053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                /* interrupted by signal, retry */
517053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                continue;
518053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            } else if (errno == EAGAIN) {
519053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                /* non-blocking EOF; we're done */
520053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                break;
521053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            } else {
5227716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate                _LOG(log, 0, "Error while reading log: %s\n",
523053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                    strerror(errno));
524053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                break;
525053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            }
526053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        } else if (actual == 0) {
5277716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate            _LOG(log, 0, "Got zero bytes while reading log: %s\n",
528053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                strerror(errno));
529053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            break;
530053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
531053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
532053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        /*
533053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown         * NOTE: if you XLOG something here, this will spin forever,
534053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown         * because you will be writing as fast as you're reading.  Any
535053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown         * high-frequency debug diagnostics should just be written to
536053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown         * the tombstone file.
537053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown         */
538053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
539053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        struct logger_entry* entry = &log_entry.entry;
540053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
541053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        if (entry->pid != (int32_t) pid) {
542053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            /* wrong pid, ignore */
543053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            continue;
544053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
545053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
546053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        if (first) {
5477716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate            _LOG(log, 0, "--------- %slog %s\n",
548053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                tailOnly ? "tail end of " : "", filename);
549053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            first = false;
550053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
551053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
552053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        /*
553053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown         * Msg format is: <priority:1><tag:N>\0<message:N>\0
554053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown         *
555053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown         * We want to display it in the same format as "logcat -v threadtime"
556053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown         * (although in this case the pid is redundant).
557053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown         *
558053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown         * TODO: scan for line breaks ('\n') and display each text line
559053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown         * on a separate line, prefixed with the header, like logcat does.
560053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown         */
561053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        static const char* kPrioChars = "!.VDIWEFS";
562053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        unsigned char prio = entry->msg[0];
563053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        char* tag = entry->msg + 1;
564053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        char* msg = tag + strlen(tag) + 1;
565053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
566053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        /* consume any trailing newlines */
567053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        char* eatnl = msg + strlen(msg) - 1;
568053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        while (eatnl >= msg && *eatnl == '\n') {
569053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            *eatnl-- = '\0';
570053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
571053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
572053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        char prioChar = (prio < strlen(kPrioChars) ? kPrioChars[prio] : '?');
573053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
574053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        char timeBuf[32];
575053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        time_t sec = (time_t) entry->sec;
576053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        struct tm tmBuf;
577053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        struct tm* ptm;
578053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        ptm = localtime_r(&sec, &tmBuf);
579053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", ptm);
580053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
581053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        if (tailOnly) {
582053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            snprintf(shortLog[shortLogNext], kShortLogLineLen,
583053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                "%s.%03d %5d %5d %c %-8s: %s",
584053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                timeBuf, entry->nsec / 1000000, entry->pid, entry->tid,
585053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                prioChar, tag, msg);
586053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            shortLogNext = (shortLogNext + 1) % kShortLogMaxLines;
587053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            shortLogCount++;
588053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        } else {
5897716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate            _LOG(log, 0, "%s.%03d %5d %5d %c %-8s: %s\n",
590053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                timeBuf, entry->nsec / 1000000, entry->pid, entry->tid,
591053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                prioChar, tag, msg);
592053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
593053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
594053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
595053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    if (tailOnly) {
596053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        int i;
597053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
598053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        /*
599053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown         * If we filled the buffer, we want to start at "next", which has
600053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown         * the oldest entry.  If we didn't, we want to start at zero.
601053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown         */
602053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        if (shortLogCount < kShortLogMaxLines) {
603053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            shortLogNext = 0;
604053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        } else {
605053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            shortLogCount = kShortLogMaxLines;  /* cap at window size */
606053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
607053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
608053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        for (i = 0; i < shortLogCount; i++) {
6097716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate            _LOG(log, 0, "%s\n", shortLog[shortLogNext]);
610053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            shortLogNext = (shortLogNext + 1) % kShortLogMaxLines;
611053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
612053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
613053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
614053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    close(logfd);
615053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
616053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
617053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown/*
618053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * Dumps the logs generated by the specified pid to the tombstone, from both
619053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * "system" and "main" log devices.  Ideally we'd interleave the output.
620053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown */
621053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic void dump_logs(log_t* log, pid_t pid, bool tailOnly)
622053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown{
623053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    dump_log_file(log, pid, "/dev/log/system", tailOnly);
624053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    dump_log_file(log, pid, "/dev/log/main", tailOnly);
625053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
626053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
627e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughesstatic void dump_abort_message(log_t* log, pid_t tid, uintptr_t address) {
628e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes  if (address == 0) {
629e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes    return;
630e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes  }
631e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes
632e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes  address += sizeof(size_t); // Skip the buffer length.
633e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes
634e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes  char msg[512];
635e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes  memset(msg, 0, sizeof(msg));
636e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes  char* p = &msg[0];
637e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes  while (p < &msg[sizeof(msg)]) {
638e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes    uint32_t data;
639e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes    if (!try_get_word_ptrace(tid, address, &data)) {
640e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes      break;
641e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes    }
642e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes    address += sizeof(uint32_t);
643e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes
644e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes    if ((*p++ = (data >>  0) & 0xff) == 0) {
645e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes      break;
646e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes    }
647e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes    if ((*p++ = (data >>  8) & 0xff) == 0) {
648e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes      break;
649e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes    }
650e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes    if ((*p++ = (data >> 16) & 0xff) == 0) {
651e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes      break;
652e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes    }
653e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes    if ((*p++ = (data >> 24) & 0xff) == 0) {
654e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes      break;
655e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes    }
656e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes  }
657e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes  msg[sizeof(msg) - 1] = '\0';
658e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes
6597716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate  _LOG(log, SCOPE_AT_FAULT, "Abort message: '%s'\n", msg);
660e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes}
661e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes
662053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown/*
663053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * Dumps all information about the specified pid to the tombstone.
664053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown */
665e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughesstatic bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, uintptr_t abort_msg_address,
666e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes                       bool dump_sibling_threads, int* total_sleep_time_usec)
667053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown{
668053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    /* don't copy log messages to tombstone unless this is a dev device */
669053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    char value[PROPERTY_VALUE_MAX];
670053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    property_get("ro.debuggable", value, "0");
671053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    bool want_logs = (value[0] == '1');
672053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
673ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate    if (log->amfd >= 0) {
674ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate        /*
675ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate         * Activity Manager protocol: binary 32-bit network-byte-order ints for the
676ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate         * pid and signal number, followed by the raw text of the dump, culminating
677ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate         * in a zero byte that marks end-of-data.
678ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate         */
679ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate        uint32_t datum = htonl(pid);
680ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate        TEMP_FAILURE_RETRY( write(log->amfd, &datum, 4) );
681ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate        datum = htonl(signal);
682ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate        TEMP_FAILURE_RETRY( write(log->amfd, &datum, 4) );
683ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate    }
684ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate
6857716aef138e8029357a7b3dc6a73b41f4de4b0adChristopher Tate    _LOG(log, SCOPE_AT_FAULT,
686053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n");
687053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    dump_build_info(log);
688d7760c1688f8276a05e33345d81639f8cb5e7c3fBen Cheng    dump_revision_info(log);
689053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    dump_thread_info(log, pid, tid, true);
690e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes    if (signal) {
691053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        dump_fault_addr(log, tid, signal);
692053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
693e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes    dump_abort_message(log, tid, abort_msg_address);
694053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
695053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    ptrace_context_t* context = load_ptrace_context(tid);
696053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    dump_thread(context, log, tid, true, total_sleep_time_usec);
697053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
698053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    if (want_logs) {
699053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        dump_logs(log, pid, true);
700053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
701053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
702053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    bool detach_failed = false;
703053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    if (dump_sibling_threads) {
704053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        detach_failed = dump_sibling_thread_report(context, log, pid, tid, total_sleep_time_usec);
705053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
706053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
707053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    free_ptrace_context(context);
708053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
709053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    if (want_logs) {
710053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        dump_logs(log, pid, false);
711053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
712ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate
713ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate    /* send EOD to the Activity Manager, then wait for its ack to avoid racing ahead
714ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate     * and killing the target out from under it */
715ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate    if (log->amfd >= 0) {
716ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate        uint8_t eodMarker = 0;
717ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate        TEMP_FAILURE_RETRY( write(log->amfd, &eodMarker, 1) );
718ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate        /* 3 sec timeout reading the ack; we're fine if that happens */
719ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate        TEMP_FAILURE_RETRY( read(log->amfd, &eodMarker, 1) );
720ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate    }
721ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate
722053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    return detach_failed;
723053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
724053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
725053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown/*
726053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * find_and_open_tombstone - find an available tombstone slot, if any, of the
727053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * form tombstone_XX where XX is 00 to MAX_TOMBSTONES-1, inclusive. If no
728053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * file is available, we reuse the least-recently-modified file.
729053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown *
730053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * Returns the path of the tombstone file, allocated using malloc().  Caller must free() it.
731053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown */
732053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic char* find_and_open_tombstone(int* fd)
733053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown{
734053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    unsigned long mtime = ULONG_MAX;
735053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    struct stat sb;
736053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
737053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    /*
738053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown     * XXX: Our stat.st_mtime isn't time_t. If it changes, as it probably ought
739053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown     * to, our logic breaks. This check will generate a warning if that happens.
740053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown     */
741053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    typecheck(mtime, sb.st_mtime);
742053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
743053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    /*
744053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown     * In a single wolf-like pass, find an available slot and, in case none
745053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown     * exist, find and record the least-recently-modified file.
746053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown     */
747053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    char path[128];
748053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    int oldest = 0;
749053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    for (int i = 0; i < MAX_TOMBSTONES; i++) {
750053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        snprintf(path, sizeof(path), TOMBSTONE_DIR"/tombstone_%02d", i);
751053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
752053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        if (!stat(path, &sb)) {
753053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            if (sb.st_mtime < mtime) {
754053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                oldest = i;
755053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                mtime = sb.st_mtime;
756053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            }
757053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            continue;
758053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
759053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        if (errno != ENOENT)
760053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            continue;
761053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
762053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        *fd = open(path, O_CREAT | O_EXCL | O_WRONLY, 0600);
763053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        if (*fd < 0)
764053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            continue;   /* raced ? */
765053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
766053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        fchown(*fd, AID_SYSTEM, AID_SYSTEM);
767053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        return strdup(path);
768053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
769053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
770053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    /* we didn't find an available file, so we clobber the oldest one */
771053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    snprintf(path, sizeof(path), TOMBSTONE_DIR"/tombstone_%02d", oldest);
772053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    *fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
773053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    if (*fd < 0) {
774053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        LOG("failed to open tombstone file '%s': %s\n", path, strerror(errno));
775053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        return NULL;
776053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
777053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    fchown(*fd, AID_SYSTEM, AID_SYSTEM);
778053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    return strdup(path);
779053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
780053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
781ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tatestatic int activity_manager_connect() {
782ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate    int amfd = socket(PF_UNIX, SOCK_STREAM, 0);
783ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate    if (amfd >= 0) {
784ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate        struct sockaddr_un address;
785ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate        int err;
786ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate
787ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate        memset(&address, 0, sizeof(address));
788ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate        address.sun_family = AF_UNIX;
789ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate        strncpy(address.sun_path, NCRASH_SOCKET_PATH, sizeof(address.sun_path));
790ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate        err = TEMP_FAILURE_RETRY( connect(amfd, (struct sockaddr*) &address, sizeof(address)) );
791ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate        if (!err) {
792ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate            struct timeval tv;
793ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate            memset(&tv, 0, sizeof(tv));
794ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate            tv.tv_sec = 1;  // tight leash
795ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate            err = setsockopt(amfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
796ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate            if (!err) {
797ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate                tv.tv_sec = 3;  // 3 seconds on handshake read
798ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate                err = setsockopt(amfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
799ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate            }
800ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate        }
801ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate        if (err) {
802ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate            close(amfd);
803ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate            amfd = -1;
804ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate        }
805ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate    }
806ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate
807ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate    return amfd;
808ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate}
809ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate
810e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hugheschar* engrave_tombstone(pid_t pid, pid_t tid, int signal, uintptr_t abort_msg_address,
811053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        bool dump_sibling_threads, bool quiet, bool* detach_failed,
812053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        int* total_sleep_time_usec) {
813053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    mkdir(TOMBSTONE_DIR, 0755);
814053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    chown(TOMBSTONE_DIR, AID_SYSTEM, AID_SYSTEM);
815053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
816f1186f3e980f5ebcc3380d8a7f746bf8a45e3531rpcraig    if (selinux_android_restorecon(TOMBSTONE_DIR) == -1) {
817f1186f3e980f5ebcc3380d8a7f746bf8a45e3531rpcraig        *detach_failed = false;
818f1186f3e980f5ebcc3380d8a7f746bf8a45e3531rpcraig        return NULL;
819f1186f3e980f5ebcc3380d8a7f746bf8a45e3531rpcraig    }
820f1186f3e980f5ebcc3380d8a7f746bf8a45e3531rpcraig
821053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    int fd;
822053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    char* path = find_and_open_tombstone(&fd);
823053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    if (!path) {
824053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        *detach_failed = false;
825053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        return NULL;
826053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
827053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
828053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    log_t log;
829053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    log.tfd = fd;
830ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate    log.amfd = activity_manager_connect();
831053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    log.quiet = quiet;
832e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes    *detach_failed = dump_crash(&log, pid, tid, signal, abort_msg_address, dump_sibling_threads,
833053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            total_sleep_time_usec);
834053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
835ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate    close(log.amfd);
836053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    close(fd);
837053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    return path;
838053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
839