1053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown/*
2fca0bd1a38597b83f6511d0c7c971fce75dc8123Mark Salyzyn * Copyright (C) 2012-2014 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
1762ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith#define LOG_TAG "DEBUG"
1862ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith
194bb477205a2446c3ba9db8df0b0446173065d9ebKévin PETIT#include <dirent.h>
204bb477205a2446c3ba9db8df0b0446173065d9ebKévin PETIT#include <errno.h>
214bb477205a2446c3ba9db8df0b0446173065d9ebKévin PETIT#include <fcntl.h>
224bb477205a2446c3ba9db8df0b0446173065d9ebKévin PETIT#include <inttypes.h>
234bb477205a2446c3ba9db8df0b0446173065d9ebKévin PETIT#include <signal.h>
24053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <stddef.h>
254bb477205a2446c3ba9db8df0b0446173065d9ebKévin PETIT#include <stdio.h>
26053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <stdlib.h>
27053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <string.h>
28053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <time.h>
29053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <sys/ptrace.h>
304bb477205a2446c3ba9db8df0b0446173065d9ebKévin PETIT#include <sys/socket.h>
31053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <sys/stat.h>
324bb477205a2446c3ba9db8df0b0446173065d9ebKévin PETIT#include <sys/un.h>
33053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
34053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <private/android_filesystem_config.h>
35053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
36989980c55d9a11766b8698a97ce5eef3d8cfa286Mark Salyzyn#include <cutils/properties.h>
3722b5cef1277a5e1d5deef7420281eafade2e2614Mark Salyzyn#include <log/log.h>
389227bd385504ace739d4451a6c5dc3d777b5bf21Colin Cross#include <log/logger.h>
39989980c55d9a11766b8698a97ce5eef3d8cfa286Mark Salyzyn#include <log/logprint.h>
40053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
4120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris#include <backtrace/Backtrace.h>
4246756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris#include <backtrace/BacktraceMap.h>
43053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
44f1186f3e980f5ebcc3380d8a7f746bf8a45e3531rpcraig#include <selinux/android.h>
45f1186f3e980f5ebcc3380d8a7f746bf8a45e3531rpcraig
4620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris#include <UniquePtr.h>
4720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris
48053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include "machine.h"
49053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include "tombstone.h"
50365e4ae74568274ffd692c12fd7285a230d49a67Christopher Ferris#include "backtrace.h"
51053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
52053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#define STACK_WORDS 16
53053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
54053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#define MAX_TOMBSTONES  10
55053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#define TOMBSTONE_DIR   "/data/tombstones"
564bb477205a2446c3ba9db8df0b0446173065d9ebKévin PETIT#define TOMBSTONE_TEMPLATE (TOMBSTONE_DIR"/tombstone_%02d")
57053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
5820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris// Must match the path defined in NativeCrashListener.java
59ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate#define NCRASH_SOCKET_PATH "/data/system/ndebugsocket"
60ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate
61855fcc3114c20ff9fd286fe1723d1413fec9685aElliott Hughesstatic bool signal_has_si_addr(int sig) {
6220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  switch (sig) {
63a323b504a70af5f143532f0ef521eb61ecddad6bElliott Hughes    case SIGBUS:
6420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    case SIGFPE:
65a323b504a70af5f143532f0ef521eb61ecddad6bElliott Hughes    case SIGILL:
6620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    case SIGSEGV:
67a639b97d4ac9f22b64fd4aa8d5ac24177817a0dcDmitriy Ivanov    case SIGTRAP:
6820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      return true;
6920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    default:
7020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      return false;
7120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
72053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
73053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
7420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferrisstatic const char* get_signame(int sig) {
7520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  switch(sig) {
7620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    case SIGABRT: return "SIGABRT";
7720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    case SIGBUS: return "SIGBUS";
7820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    case SIGFPE: return "SIGFPE";
79a323b504a70af5f143532f0ef521eb61ecddad6bElliott Hughes    case SIGILL: return "SIGILL";
8020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    case SIGPIPE: return "SIGPIPE";
81a323b504a70af5f143532f0ef521eb61ecddad6bElliott Hughes    case SIGSEGV: return "SIGSEGV";
82855fcc3114c20ff9fd286fe1723d1413fec9685aElliott Hughes#if defined(SIGSTKFLT)
8320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    case SIGSTKFLT: return "SIGSTKFLT";
84231e3c83a3a70b11160fb0da108ebf2e0e7470e2Chris Dearman#endif
8520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    case SIGSTOP: return "SIGSTOP";
86a323b504a70af5f143532f0ef521eb61ecddad6bElliott Hughes    case SIGTRAP: return "SIGTRAP";
8720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    default: return "?";
8820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
89053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
90053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
9120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferrisstatic const char* get_sigcode(int signo, int code) {
9220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  // Try the signal-specific codes...
9320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  switch (signo) {
94053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    case SIGILL:
9520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      switch (code) {
96053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case ILL_ILLOPC: return "ILL_ILLOPC";
97053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case ILL_ILLOPN: return "ILL_ILLOPN";
98053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case ILL_ILLADR: return "ILL_ILLADR";
99053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case ILL_ILLTRP: return "ILL_ILLTRP";
100053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case ILL_PRVOPC: return "ILL_PRVOPC";
101053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case ILL_PRVREG: return "ILL_PRVREG";
102053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case ILL_COPROC: return "ILL_COPROC";
103053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case ILL_BADSTK: return "ILL_BADSTK";
10420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      }
105bd395b9a142209228ec8c03d3eb3f3e97a89f9b5Elliott Hughes      static_assert(NSIGILL == ILL_BADSTK, "missing ILL_* si_code");
10620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      break;
107053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    case SIGBUS:
10820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      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";
112bd395b9a142209228ec8c03d3eb3f3e97a89f9b5Elliott Hughes        case BUS_MCEERR_AR: return "BUS_MCEERR_AR";
113bd395b9a142209228ec8c03d3eb3f3e97a89f9b5Elliott Hughes        case BUS_MCEERR_AO: return "BUS_MCEERR_AO";
11420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      }
115bd395b9a142209228ec8c03d3eb3f3e97a89f9b5Elliott Hughes      static_assert(NSIGBUS == BUS_MCEERR_AO, "missing BUS_* si_code");
11620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      break;
117053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    case SIGFPE:
11820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      switch (code) {
119053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case FPE_INTDIV: return "FPE_INTDIV";
120053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case FPE_INTOVF: return "FPE_INTOVF";
121053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case FPE_FLTDIV: return "FPE_FLTDIV";
122053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case FPE_FLTOVF: return "FPE_FLTOVF";
123053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case FPE_FLTUND: return "FPE_FLTUND";
124053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case FPE_FLTRES: return "FPE_FLTRES";
125053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case FPE_FLTINV: return "FPE_FLTINV";
126053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case FPE_FLTSUB: return "FPE_FLTSUB";
12720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      }
128bd395b9a142209228ec8c03d3eb3f3e97a89f9b5Elliott Hughes      static_assert(NSIGFPE == FPE_FLTSUB, "missing FPE_* si_code");
12920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      break;
130053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    case SIGSEGV:
13120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      switch (code) {
132053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case SEGV_MAPERR: return "SEGV_MAPERR";
133053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        case SEGV_ACCERR: return "SEGV_ACCERR";
13420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      }
135bd395b9a142209228ec8c03d3eb3f3e97a89f9b5Elliott Hughes      static_assert(NSIGSEGV == SEGV_ACCERR, "missing SEGV_* si_code");
13620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      break;
1378f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes    case SIGTRAP:
13820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      switch (code) {
1398f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes        case TRAP_BRKPT: return "TRAP_BRKPT";
1408f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes        case TRAP_TRACE: return "TRAP_TRACE";
141bd395b9a142209228ec8c03d3eb3f3e97a89f9b5Elliott Hughes        case TRAP_BRANCH: return "TRAP_BRANCH";
142bd395b9a142209228ec8c03d3eb3f3e97a89f9b5Elliott Hughes        case TRAP_HWBKPT: return "TRAP_HWBKPT";
14320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      }
144bd395b9a142209228ec8c03d3eb3f3e97a89f9b5Elliott Hughes      static_assert(NSIGTRAP == TRAP_HWBKPT, "missing TRAP_* si_code");
14520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      break;
14620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
14720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  // Then the other codes...
14820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  switch (code) {
14920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    case SI_USER: return "SI_USER";
15020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    case SI_KERNEL: return "SI_KERNEL";
15120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    case SI_QUEUE: return "SI_QUEUE";
15220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    case SI_TIMER: return "SI_TIMER";
15320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    case SI_MESGQ: return "SI_MESGQ";
1548f7d4430f341c555533ef6effd883a5aae1ce160Elliott Hughes    case SI_ASYNCIO: return "SI_ASYNCIO";
15520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    case SI_SIGIO: return "SI_SIGIO";
15620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    case SI_TKILL: return "SI_TKILL";
157bd395b9a142209228ec8c03d3eb3f3e97a89f9b5Elliott Hughes    case SI_DETHREAD: return "SI_DETHREAD";
15820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
15920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  // Then give up...
16020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  return "?";
161053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
162053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
1639c8dacce55455cacd282789982ef931e55bb4a40Brigid Smithstatic void dump_header_info(log_t* log) {
16420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  char fingerprint[PROPERTY_VALUE_MAX];
1659c8dacce55455cacd282789982ef931e55bb4a40Brigid Smith  char revision[PROPERTY_VALUE_MAX];
166053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
16720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  property_get("ro.build.fingerprint", fingerprint, "unknown");
1689c8dacce55455cacd282789982ef931e55bb4a40Brigid Smith  property_get("ro.revision", revision, "unknown");
169053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
17062ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith  _LOG(log, logtype::HEADER, "Build fingerprint: '%s'\n", fingerprint);
17162ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith  _LOG(log, logtype::HEADER, "Revision: '%s'\n", revision);
17262ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith  _LOG(log, logtype::HEADER, "ABI: '%s'\n", ABI_STRING);
173053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
174053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
175855fcc3114c20ff9fd286fe1723d1413fec9685aElliott Hughesstatic void dump_signal_info(log_t* log, pid_t tid, int signal, int si_code) {
17620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  siginfo_t si;
17720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  memset(&si, 0, sizeof(si));
178855fcc3114c20ff9fd286fe1723d1413fec9685aElliott Hughes  if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si) == -1) {
17962ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith    _LOG(log, logtype::HEADER, "cannot get siginfo: %s\n", strerror(errno));
180855fcc3114c20ff9fd286fe1723d1413fec9685aElliott Hughes    return;
181855fcc3114c20ff9fd286fe1723d1413fec9685aElliott Hughes  }
182855fcc3114c20ff9fd286fe1723d1413fec9685aElliott Hughes
183855fcc3114c20ff9fd286fe1723d1413fec9685aElliott Hughes  // bionic has to re-raise some signals, which overwrites the si_code with SI_TKILL.
184855fcc3114c20ff9fd286fe1723d1413fec9685aElliott Hughes  si.si_code = si_code;
185855fcc3114c20ff9fd286fe1723d1413fec9685aElliott Hughes
186855fcc3114c20ff9fd286fe1723d1413fec9685aElliott Hughes  char addr_desc[32]; // ", fault addr 0x1234"
187855fcc3114c20ff9fd286fe1723d1413fec9685aElliott Hughes  if (signal_has_si_addr(signal)) {
188855fcc3114c20ff9fd286fe1723d1413fec9685aElliott Hughes    snprintf(addr_desc, sizeof(addr_desc), "%p", si.si_addr);
18920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  } else {
190855fcc3114c20ff9fd286fe1723d1413fec9685aElliott Hughes    snprintf(addr_desc, sizeof(addr_desc), "--------");
19120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
192855fcc3114c20ff9fd286fe1723d1413fec9685aElliott Hughes
19362ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith  _LOG(log, logtype::HEADER, "signal %d (%s), code %d (%s), fault addr %s\n",
194855fcc3114c20ff9fd286fe1723d1413fec9685aElliott Hughes       signal, get_signame(signal), si.si_code, get_sigcode(signal, si.si_code), addr_desc);
195053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
196053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
19762ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smithstatic void dump_thread_info(log_t* log, pid_t pid, pid_t tid) {
19820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  char path[64];
19920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  char threadnamebuf[1024];
20020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  char* threadname = NULL;
20120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  FILE *fp;
20220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris
20320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  snprintf(path, sizeof(path), "/proc/%d/comm", tid);
20420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  if ((fp = fopen(path, "r"))) {
20520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    threadname = fgets(threadnamebuf, sizeof(threadnamebuf), fp);
20620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    fclose(fp);
20720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    if (threadname) {
20820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      size_t len = strlen(threadname);
20920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      if (len && threadname[len - 1] == '\n') {
21020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris        threadname[len - 1] = '\0';
21120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      }
212053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
21320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
2142f2e79de0c5cdf5494a54b44b8bee24c5cf2851dMark Salyzyn  // Blacklist logd, logd.reader, logd.writer, logd.auditd, logd.control ...
2152f2e79de0c5cdf5494a54b44b8bee24c5cf2851dMark Salyzyn  static const char logd[] = "logd";
2162f2e79de0c5cdf5494a54b44b8bee24c5cf2851dMark Salyzyn  if (!strncmp(threadname, logd, sizeof(logd) - 1)
2172f2e79de0c5cdf5494a54b44b8bee24c5cf2851dMark Salyzyn      && (!threadname[sizeof(logd) - 1] || (threadname[sizeof(logd) - 1] == '.'))) {
2182f2e79de0c5cdf5494a54b44b8bee24c5cf2851dMark Salyzyn    log->should_retrieve_logcat = false;
2192f2e79de0c5cdf5494a54b44b8bee24c5cf2851dMark Salyzyn  }
220053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
22162ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith  char procnamebuf[1024];
22262ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith  char* procname = NULL;
22320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris
22462ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith  snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
22562ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith  if ((fp = fopen(path, "r"))) {
22662ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith    procname = fgets(procnamebuf, sizeof(procnamebuf), fp);
22762ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith    fclose(fp);
22820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
22962ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith
230f473200d355a10dca1260948acc85bf059034768Brigid Smith  _LOG(log, logtype::HEADER, "pid: %d, tid: %d, name: %s  >>> %s <<<\n", pid, tid,
23162ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith       threadname ? threadname : "UNKNOWN", procname ? procname : "UNKNOWN");
232053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
233053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
23420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferrisstatic void dump_stack_segment(
23562ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith    Backtrace* backtrace, log_t* log, uintptr_t* sp, size_t words, int label) {
23620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  for (size_t i = 0; i < words; i++) {
237c6c194ced095df5e777b8fa24527ebd29c8fef54Pavel Chupin    word_t stack_content;
23820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    if (!backtrace->ReadWord(*sp, &stack_content)) {
23920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      break;
24020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    }
241053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
24246756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris    const backtrace_map_t* map = backtrace->FindMap(stack_content);
24346756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris    const char* map_name;
24446756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris    if (!map) {
24520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      map_name = "";
24646756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris    } else {
24746756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris      map_name = map->name.c_str();
24820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    }
24920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    uintptr_t offset = 0;
25020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    std::string func_name(backtrace->GetFunctionName(stack_content, &offset));
25120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    if (!func_name.empty()) {
25220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      if (!i && label >= 0) {
25320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris        if (offset) {
25462ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith          _LOG(log, logtype::STACK, "    #%02d  %" PRIPTR "  %" PRIPTR "  %s (%s+%" PRIuPTR ")\n",
25520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris               label, *sp, stack_content, map_name, func_name.c_str(), offset);
25620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris        } else {
25762ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith          _LOG(log, logtype::STACK, "    #%02d  %" PRIPTR "  %" PRIPTR "  %s (%s)\n",
25820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris               label, *sp, stack_content, map_name, func_name.c_str());
259365e4ae74568274ffd692c12fd7285a230d49a67Christopher Ferris        }
26020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      } else {
26120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris        if (offset) {
26262ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith          _LOG(log, logtype::STACK, "         %" PRIPTR "  %" PRIPTR "  %s (%s+%" PRIuPTR ")\n",
26320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris               *sp, stack_content, map_name, func_name.c_str(), offset);
264053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        } else {
26562ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith          _LOG(log, logtype::STACK, "         %" PRIPTR "  %" PRIPTR "  %s (%s)\n",
26620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris               *sp, stack_content, map_name, func_name.c_str());
267053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
26820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      }
26920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    } else {
27020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      if (!i && label >= 0) {
27162ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith        _LOG(log, logtype::STACK, "    #%02d  %" PRIPTR "  %" PRIPTR "  %s\n",
27220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris             label, *sp, stack_content, map_name);
27320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      } else {
27462ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith        _LOG(log, logtype::STACK, "         %" PRIPTR "  %" PRIPTR "  %s\n",
27520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris             *sp, stack_content, map_name);
27620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      }
277053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
27820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris
279c6c194ced095df5e777b8fa24527ebd29c8fef54Pavel Chupin    *sp += sizeof(word_t);
28020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
281053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
282053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
28362ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smithstatic void dump_stack(Backtrace* backtrace, log_t* log) {
28420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  size_t first = 0, last;
28520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  for (size_t i = 0; i < backtrace->NumFrames(); i++) {
28620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    const backtrace_frame_data_t* frame = backtrace->GetFrame(i);
28720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    if (frame->sp) {
28820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      if (!first) {
28920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris        first = i+1;
29020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      }
29120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      last = i;
292053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
29320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
29420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  if (!first) {
29520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    return;
29620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
29720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  first--;
29820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris
29920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  // Dump a few words before the first frame.
300c6c194ced095df5e777b8fa24527ebd29c8fef54Pavel Chupin  word_t sp = backtrace->GetFrame(first)->sp - STACK_WORDS * sizeof(word_t);
30162ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith  dump_stack_segment(backtrace, log, &sp, STACK_WORDS, -1);
30220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris
30320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  // Dump a few words from all successive frames.
30420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  // Only log the first 3 frames, put the rest in the tombstone.
30520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  for (size_t i = first; i <= last; i++) {
30620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    const backtrace_frame_data_t* frame = backtrace->GetFrame(i);
30720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    if (sp != frame->sp) {
30862ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith      _LOG(log, logtype::STACK, "         ........  ........\n");
30920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      sp = frame->sp;
31020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    }
31120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    if (i == last) {
31262ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith      dump_stack_segment(backtrace, log, &sp, STACK_WORDS, i);
31320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      if (sp < frame->sp + frame->stack_size) {
31462ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith        _LOG(log, logtype::STACK, "         ........  ........\n");
31520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      }
31620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    } else {
317c6c194ced095df5e777b8fa24527ebd29c8fef54Pavel Chupin      size_t words = frame->stack_size / sizeof(word_t);
31820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      if (words == 0) {
31920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris        words = 1;
32020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      } else if (words > STACK_WORDS) {
32120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris        words = STACK_WORDS;
32220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      }
32362ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith      dump_stack_segment(backtrace, log, &sp, words, i);
324053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
32520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
326053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
327053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
32862ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smithstatic void dump_backtrace_and_stack(Backtrace* backtrace, log_t* log) {
32920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  if (backtrace->NumFrames()) {
33062ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith    _LOG(log, logtype::BACKTRACE, "\nbacktrace:\n");
33162ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith    dump_backtrace_to_log(backtrace, log, "    ");
332365e4ae74568274ffd692c12fd7285a230d49a67Christopher Ferris
33362ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith    _LOG(log, logtype::STACK, "\nstack:\n");
33462ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith    dump_stack(backtrace, log);
33520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
336053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
337053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
3382e8290463eff6e66e17b8afa0bcdfe4ff2e920cfBrigid Smithstatic void dump_map(log_t* log, const backtrace_map_t* map, bool fault_addr) {
3397e775952e173b02d1930c56885da4ab7a9e62e0aElliott Hughes  _LOG(log, logtype::MAPS, "%s%" PRIPTR "-%" PRIPTR " %c%c%c  %7" PRIdPTR "  %s\n",
3408606eaa7700609a2f9f2383b954b4e64dbc4c827Brigid Smith         (fault_addr? "--->" : "    "), map->start, map->end - 1,
34146756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris         (map->flags & PROT_READ) ? 'r' : '-', (map->flags & PROT_WRITE) ? 'w' : '-',
3428606eaa7700609a2f9f2383b954b4e64dbc4c827Brigid Smith         (map->flags & PROT_EXEC) ? 'x' : '-',
3438606eaa7700609a2f9f2383b954b4e64dbc4c827Brigid Smith         (map->end - map->start), map->name.c_str());
344d1420be6133fc5ba71d59315936fb85239ea78b1Elliott Hughes}
345d1420be6133fc5ba71d59315936fb85239ea78b1Elliott Hughes
34662ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smithstatic void dump_nearby_maps(BacktraceMap* map, log_t* log, pid_t tid) {
34720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  siginfo_t si;
34820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  memset(&si, 0, sizeof(si));
34920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si)) {
35062ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith    _LOG(log, logtype::MAPS, "cannot get siginfo for %d: %s\n", tid, strerror(errno));
35120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    return;
35220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
353053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
354a639b97d4ac9f22b64fd4aa8d5ac24177817a0dcDmitriy Ivanov  bool has_fault_address = signal_has_si_addr(si.si_signo);
35546756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris  uintptr_t addr = reinterpret_cast<uintptr_t>(si.si_addr);
356053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
357a639b97d4ac9f22b64fd4aa8d5ac24177817a0dcDmitriy Ivanov  _LOG(log, logtype::MAPS, "\nmemory map: %s\n", has_fault_address ? "(fault address prefixed with --->)" : "");
3588606eaa7700609a2f9f2383b954b4e64dbc4c827Brigid Smith
359a639b97d4ac9f22b64fd4aa8d5ac24177817a0dcDmitriy Ivanov  if (has_fault_address && (addr < map->begin()->start)) {
3608606eaa7700609a2f9f2383b954b4e64dbc4c827Brigid Smith    _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " before any mapped regions\n", addr);
3618606eaa7700609a2f9f2383b954b4e64dbc4c827Brigid Smith  }
36220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris
3638606eaa7700609a2f9f2383b954b4e64dbc4c827Brigid Smith  BacktraceMap::const_iterator prev = map->begin();
36446756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris  for (BacktraceMap::const_iterator it = map->begin(); it != map->end(); ++it) {
3658606eaa7700609a2f9f2383b954b4e64dbc4c827Brigid Smith    if (addr >= (*prev).end && addr < (*it).start) {
3668606eaa7700609a2f9f2383b954b4e64dbc4c827Brigid Smith      _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " between mapped regions\n", addr);
3672e8290463eff6e66e17b8afa0bcdfe4ff2e920cfBrigid Smith    }
3688606eaa7700609a2f9f2383b954b4e64dbc4c827Brigid Smith    prev = it;
369a639b97d4ac9f22b64fd4aa8d5ac24177817a0dcDmitriy Ivanov    bool in_map = has_fault_address && (addr >= (*it).start) && (addr < (*it).end);
3708606eaa7700609a2f9f2383b954b4e64dbc4c827Brigid Smith    dump_map(log, &*it, in_map);
3712e8290463eff6e66e17b8afa0bcdfe4ff2e920cfBrigid Smith  }
372a639b97d4ac9f22b64fd4aa8d5ac24177817a0dcDmitriy Ivanov  if (has_fault_address && (addr >= (*prev).end)) {
3738606eaa7700609a2f9f2383b954b4e64dbc4c827Brigid Smith    _LOG(log, logtype::MAPS, "--->Fault address falls at %" PRIPTR " after any mapped regions\n", addr);
37420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
375053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
376053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
37784ddb34a3af77dbe490aaa07b738bbfd7109d5baChristopher Ferrisstatic void dump_thread(Backtrace* backtrace, log_t* log) {
37862ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith  dump_registers(log, backtrace->Tid());
37962ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith  dump_backtrace_and_stack(backtrace, log);
38062ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith
38162ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith  dump_memory_and_code(log, backtrace->Tid());
38262ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith  dump_nearby_maps(backtrace->GetMap(), log, backtrace->Tid());
383053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
384053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
38520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris// Return true if some thread is not detached cleanly
386365e4ae74568274ffd692c12fd7285a230d49a67Christopher Ferrisstatic bool dump_sibling_thread_report(
38746756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris    log_t* log, pid_t pid, pid_t tid, int* total_sleep_time_usec, BacktraceMap* map) {
38820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  char task_path[64];
38962ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith
39020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid);
39120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris
39220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  DIR* d = opendir(task_path);
39320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  // Bail early if the task directory cannot be opened
39420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  if (d == NULL) {
39550eb546ec1584c04cf18f1941a042d7c5d045a67Brigid Smith    ALOGE("Cannot open /proc/%d/task\n", pid);
39620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    return false;
39720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
39820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris
39920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  bool detach_failed = false;
40020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  struct dirent* de;
40120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  while ((de = readdir(d)) != NULL) {
40220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    // Ignore "." and ".."
40320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
40420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      continue;
405053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
406053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
40720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    // The main thread at fault has been handled individually
40820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    char* end;
40920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    pid_t new_tid = strtoul(de->d_name, &end, 10);
41020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    if (*end || new_tid == tid) {
41120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      continue;
41220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    }
413053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
41420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    // Skip this thread if cannot ptrace it
41520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    if (ptrace(PTRACE_ATTACH, new_tid, 0, 0) < 0) {
41650eb546ec1584c04cf18f1941a042d7c5d045a67Brigid Smith      _LOG(log, logtype::ERROR, "ptrace attach to %d failed: %s\n", new_tid, strerror(errno));
41720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      continue;
41820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    }
419053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
42084ddb34a3af77dbe490aaa07b738bbfd7109d5baChristopher Ferris    if (wait_for_sigstop(new_tid, total_sleep_time_usec, &detach_failed) == -1) {
42184ddb34a3af77dbe490aaa07b738bbfd7109d5baChristopher Ferris      continue;
42284ddb34a3af77dbe490aaa07b738bbfd7109d5baChristopher Ferris    }
42384ddb34a3af77dbe490aaa07b738bbfd7109d5baChristopher Ferris
424f473200d355a10dca1260948acc85bf059034768Brigid Smith    log->current_tid = new_tid;
42562ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith    _LOG(log, logtype::THREAD, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n");
42662ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith    dump_thread_info(log, pid, new_tid);
42762ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith
42846756821c4fe238f12a6e5ea18c356398f8d8795Christopher Ferris    UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, new_tid, map));
42920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    if (backtrace->Unwind(0)) {
43084ddb34a3af77dbe490aaa07b738bbfd7109d5baChristopher Ferris      dump_thread(backtrace.get(), log);
43120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    }
432053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
43362ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith    log->current_tid = log->crashed_tid;
43462ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith
43520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    if (ptrace(PTRACE_DETACH, new_tid, 0, 0) != 0) {
43650eb546ec1584c04cf18f1941a042d7c5d045a67Brigid Smith      _LOG(log, logtype::ERROR, "ptrace detach from %d failed: %s\n", new_tid, strerror(errno));
43720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      detach_failed = true;
438053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
43920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
440053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
44120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  closedir(d);
44220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  return detach_failed;
443053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
444053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
44520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris// Reads the contents of the specified log device, filters out the entries
44620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris// that don't match the specified pid, and writes them to the tombstone file.
44720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris//
44817e85c06716fe1a6973d46e6b8b19c6b72de1c81Mark Salyzyn// If "tail" is non-zero, log the last "tail" number of lines.
449989980c55d9a11766b8698a97ce5eef3d8cfa286Mark Salyzynstatic EventTagMap* g_eventTagMap = NULL;
450989980c55d9a11766b8698a97ce5eef3d8cfa286Mark Salyzyn
45117e85c06716fe1a6973d46e6b8b19c6b72de1c81Mark Salyzynstatic void dump_log_file(
45217e85c06716fe1a6973d46e6b8b19c6b72de1c81Mark Salyzyn    log_t* log, pid_t pid, const char* filename, unsigned int tail) {
45320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  bool first = true;
45417e85c06716fe1a6973d46e6b8b19c6b72de1c81Mark Salyzyn  struct logger_list* logger_list;
45520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris
4562f2e79de0c5cdf5494a54b44b8bee24c5cf2851dMark Salyzyn  if (!log->should_retrieve_logcat) {
4572f2e79de0c5cdf5494a54b44b8bee24c5cf2851dMark Salyzyn    return;
4582f2e79de0c5cdf5494a54b44b8bee24c5cf2851dMark Salyzyn  }
4592f2e79de0c5cdf5494a54b44b8bee24c5cf2851dMark Salyzyn
46022b5cef1277a5e1d5deef7420281eafade2e2614Mark Salyzyn  logger_list = android_logger_list_open(
46117e85c06716fe1a6973d46e6b8b19c6b72de1c81Mark Salyzyn      android_name_to_log_id(filename), O_RDONLY | O_NONBLOCK, tail, pid);
46220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris
46322b5cef1277a5e1d5deef7420281eafade2e2614Mark Salyzyn  if (!logger_list) {
46450eb546ec1584c04cf18f1941a042d7c5d045a67Brigid Smith    ALOGE("Unable to open %s: %s\n", filename, strerror(errno));
46520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    return;
46620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
46720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris
46822b5cef1277a5e1d5deef7420281eafade2e2614Mark Salyzyn  struct log_msg log_entry;
46920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris
47020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  while (true) {
47122b5cef1277a5e1d5deef7420281eafade2e2614Mark Salyzyn    ssize_t actual = android_logger_list_read(logger_list, &log_entry);
47217e85c06716fe1a6973d46e6b8b19c6b72de1c81Mark Salyzyn    struct logger_entry* entry;
47322b5cef1277a5e1d5deef7420281eafade2e2614Mark Salyzyn
47420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    if (actual < 0) {
47522b5cef1277a5e1d5deef7420281eafade2e2614Mark Salyzyn      if (actual == -EINTR) {
47620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris        // interrupted by signal, retry
47720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris        continue;
47822b5cef1277a5e1d5deef7420281eafade2e2614Mark Salyzyn      } else if (actual == -EAGAIN) {
47920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris        // non-blocking EOF; we're done
48020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris        break;
48120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      } else {
48250eb546ec1584c04cf18f1941a042d7c5d045a67Brigid Smith        _LOG(log, logtype::ERROR, "Error while reading log: %s\n",
48322b5cef1277a5e1d5deef7420281eafade2e2614Mark Salyzyn          strerror(-actual));
48420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris        break;
48520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      }
48620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    } else if (actual == 0) {
48750eb546ec1584c04cf18f1941a042d7c5d045a67Brigid Smith      _LOG(log, logtype::ERROR, "Got zero bytes while reading log: %s\n",
48822b5cef1277a5e1d5deef7420281eafade2e2614Mark Salyzyn        strerror(errno));
48920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      break;
490053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
491053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
49250eb546ec1584c04cf18f1941a042d7c5d045a67Brigid Smith    // NOTE: if you ALOGV something here, this will spin forever,
49320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    // because you will be writing as fast as you're reading.  Any
49420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    // high-frequency debug diagnostics should just be written to
49520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    // the tombstone file.
496053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
49717e85c06716fe1a6973d46e6b8b19c6b72de1c81Mark Salyzyn    entry = &log_entry.entry_v1;
498053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
49920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    if (first) {
500e43290d7ed6e90bd64c93fe8796f5aeaf1e68436Mark Salyzyn      _LOG(log, logtype::LOGS, "--------- %slog %s\n",
50122b5cef1277a5e1d5deef7420281eafade2e2614Mark Salyzyn        tail ? "tail end of " : "", filename);
50220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      first = false;
50320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    }
504053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
50520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    // Msg format is: <priority:1><tag:N>\0<message:N>\0
50620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    //
50720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    // We want to display it in the same format as "logcat -v threadtime"
50820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    // (although in this case the pid is redundant).
50920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    static const char* kPrioChars = "!.VDIWEFS";
51022b5cef1277a5e1d5deef7420281eafade2e2614Mark Salyzyn    unsigned hdr_size = log_entry.entry.hdr_size;
51122b5cef1277a5e1d5deef7420281eafade2e2614Mark Salyzyn    if (!hdr_size) {
51222b5cef1277a5e1d5deef7420281eafade2e2614Mark Salyzyn      hdr_size = sizeof(log_entry.entry_v1);
51322b5cef1277a5e1d5deef7420281eafade2e2614Mark Salyzyn    }
514989980c55d9a11766b8698a97ce5eef3d8cfa286Mark Salyzyn    char* msg = reinterpret_cast<char*>(log_entry.buf) + hdr_size;
515989980c55d9a11766b8698a97ce5eef3d8cfa286Mark Salyzyn
516989980c55d9a11766b8698a97ce5eef3d8cfa286Mark Salyzyn    char timeBuf[32];
517989980c55d9a11766b8698a97ce5eef3d8cfa286Mark Salyzyn    time_t sec = static_cast<time_t>(entry->sec);
518989980c55d9a11766b8698a97ce5eef3d8cfa286Mark Salyzyn    struct tm tmBuf;
519989980c55d9a11766b8698a97ce5eef3d8cfa286Mark Salyzyn    struct tm* ptm;
520989980c55d9a11766b8698a97ce5eef3d8cfa286Mark Salyzyn    ptm = localtime_r(&sec, &tmBuf);
521989980c55d9a11766b8698a97ce5eef3d8cfa286Mark Salyzyn    strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", ptm);
522989980c55d9a11766b8698a97ce5eef3d8cfa286Mark Salyzyn
523989980c55d9a11766b8698a97ce5eef3d8cfa286Mark Salyzyn    if (log_entry.id() == LOG_ID_EVENTS) {
524989980c55d9a11766b8698a97ce5eef3d8cfa286Mark Salyzyn      if (!g_eventTagMap) {
525989980c55d9a11766b8698a97ce5eef3d8cfa286Mark Salyzyn        g_eventTagMap = android_openEventTagMap(EVENT_TAG_MAP_FILE);
526989980c55d9a11766b8698a97ce5eef3d8cfa286Mark Salyzyn      }
527989980c55d9a11766b8698a97ce5eef3d8cfa286Mark Salyzyn      AndroidLogEntry e;
528989980c55d9a11766b8698a97ce5eef3d8cfa286Mark Salyzyn      char buf[512];
529989980c55d9a11766b8698a97ce5eef3d8cfa286Mark Salyzyn      android_log_processBinaryLogBuffer(entry, &e, g_eventTagMap, buf, sizeof(buf));
53062ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith      _LOG(log, logtype::LOGS, "%s.%03d %5d %5d %c %-8s: %s\n",
531989980c55d9a11766b8698a97ce5eef3d8cfa286Mark Salyzyn         timeBuf, entry->nsec / 1000000, entry->pid, entry->tid,
532989980c55d9a11766b8698a97ce5eef3d8cfa286Mark Salyzyn         'I', e.tag, e.message);
533989980c55d9a11766b8698a97ce5eef3d8cfa286Mark Salyzyn      continue;
534989980c55d9a11766b8698a97ce5eef3d8cfa286Mark Salyzyn    }
535989980c55d9a11766b8698a97ce5eef3d8cfa286Mark Salyzyn
53622b5cef1277a5e1d5deef7420281eafade2e2614Mark Salyzyn    unsigned char prio = msg[0];
53722b5cef1277a5e1d5deef7420281eafade2e2614Mark Salyzyn    char* tag = msg + 1;
53822b5cef1277a5e1d5deef7420281eafade2e2614Mark Salyzyn    msg = tag + strlen(tag) + 1;
539053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
54020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    // consume any trailing newlines
541fca0bd1a38597b83f6511d0c7c971fce75dc8123Mark Salyzyn    char* nl = msg + strlen(msg) - 1;
542fca0bd1a38597b83f6511d0c7c971fce75dc8123Mark Salyzyn    while (nl >= msg && *nl == '\n') {
54317e85c06716fe1a6973d46e6b8b19c6b72de1c81Mark Salyzyn      *nl-- = '\0';
54420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    }
545053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
54620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    char prioChar = (prio < strlen(kPrioChars) ? kPrioChars[prio] : '?');
547053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
548fca0bd1a38597b83f6511d0c7c971fce75dc8123Mark Salyzyn    // Look for line breaks ('\n') and display each text line
549fca0bd1a38597b83f6511d0c7c971fce75dc8123Mark Salyzyn    // on a separate line, prefixed with the header, like logcat does.
550fca0bd1a38597b83f6511d0c7c971fce75dc8123Mark Salyzyn    do {
551fca0bd1a38597b83f6511d0c7c971fce75dc8123Mark Salyzyn      nl = strchr(msg, '\n');
552fca0bd1a38597b83f6511d0c7c971fce75dc8123Mark Salyzyn      if (nl) {
553fca0bd1a38597b83f6511d0c7c971fce75dc8123Mark Salyzyn        *nl = '\0';
554fca0bd1a38597b83f6511d0c7c971fce75dc8123Mark Salyzyn        ++nl;
555fca0bd1a38597b83f6511d0c7c971fce75dc8123Mark Salyzyn      }
556fca0bd1a38597b83f6511d0c7c971fce75dc8123Mark Salyzyn
55762ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith      _LOG(log, logtype::LOGS, "%s.%03d %5d %5d %c %-8s: %s\n",
558fca0bd1a38597b83f6511d0c7c971fce75dc8123Mark Salyzyn         timeBuf, entry->nsec / 1000000, entry->pid, entry->tid,
559fca0bd1a38597b83f6511d0c7c971fce75dc8123Mark Salyzyn         prioChar, tag, msg);
560fca0bd1a38597b83f6511d0c7c971fce75dc8123Mark Salyzyn    } while ((msg = nl));
56120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
562053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
56322b5cef1277a5e1d5deef7420281eafade2e2614Mark Salyzyn  android_logger_list_free(logger_list);
564053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
565053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
56620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris// Dumps the logs generated by the specified pid to the tombstone, from both
56720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris// "system" and "main" log devices.  Ideally we'd interleave the output.
56817e85c06716fe1a6973d46e6b8b19c6b72de1c81Mark Salyzynstatic void dump_logs(log_t* log, pid_t pid, unsigned int tail) {
56922b5cef1277a5e1d5deef7420281eafade2e2614Mark Salyzyn  dump_log_file(log, pid, "system", tail);
57022b5cef1277a5e1d5deef7420281eafade2e2614Mark Salyzyn  dump_log_file(log, pid, "main", tail);
571053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
572053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
57320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferrisstatic void dump_abort_message(Backtrace* backtrace, log_t* log, uintptr_t address) {
574e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes  if (address == 0) {
575e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes    return;
576e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes  }
577e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes
578e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes  address += sizeof(size_t); // Skip the buffer length.
579e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes
580e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes  char msg[512];
581e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes  memset(msg, 0, sizeof(msg));
582e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes  char* p = &msg[0];
583e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes  while (p < &msg[sizeof(msg)]) {
584c6c194ced095df5e777b8fa24527ebd29c8fef54Pavel Chupin    word_t data;
585c6c194ced095df5e777b8fa24527ebd29c8fef54Pavel Chupin    size_t len = sizeof(word_t);
58620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    if (!backtrace->ReadWord(address, &data)) {
587e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes      break;
588e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes    }
589c6c194ced095df5e777b8fa24527ebd29c8fef54Pavel Chupin    address += sizeof(word_t);
590e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes
591c6c194ced095df5e777b8fa24527ebd29c8fef54Pavel Chupin    while (len > 0 && (*p++ = (data >> (sizeof(word_t) - len) * 8) & 0xff) != 0)
592c6c194ced095df5e777b8fa24527ebd29c8fef54Pavel Chupin       len--;
593e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes  }
594e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes  msg[sizeof(msg) - 1] = '\0';
595e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes
59662ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith  _LOG(log, logtype::HEADER, "Abort message: '%s'\n", msg);
597e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes}
598e5f8a692e44be89dc4c062517eadfb88184c4770Elliott Hughes
59920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris// Dumps all information about the specified pid to the tombstone.
600855fcc3114c20ff9fd286fe1723d1413fec9685aElliott Hughesstatic bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, int si_code,
601855fcc3114c20ff9fd286fe1723d1413fec9685aElliott Hughes                       uintptr_t abort_msg_address, bool dump_sibling_threads,
602855fcc3114c20ff9fd286fe1723d1413fec9685aElliott Hughes                       int* total_sleep_time_usec) {
60320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  // don't copy log messages to tombstone unless this is a dev device
60420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  char value[PROPERTY_VALUE_MAX];
60520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  property_get("ro.debuggable", value, "0");
60620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  bool want_logs = (value[0] == '1');
60720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris
60820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  if (log->amfd >= 0) {
60920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    // Activity Manager protocol: binary 32-bit network-byte-order ints for the
61020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    // pid and signal number, followed by the raw text of the dump, culminating
61120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    // in a zero byte that marks end-of-data.
61220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    uint32_t datum = htonl(pid);
61320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    TEMP_FAILURE_RETRY( write(log->amfd, &datum, 4) );
61420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    datum = htonl(signal);
61520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    TEMP_FAILURE_RETRY( write(log->amfd, &datum, 4) );
61620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
617053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
61862ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith  _LOG(log, logtype::HEADER,
61920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris       "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n");
6209c8dacce55455cacd282789982ef931e55bb4a40Brigid Smith  dump_header_info(log);
62162ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith  dump_thread_info(log, pid, tid);
62262ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith
62320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  if (signal) {
624855fcc3114c20ff9fd286fe1723d1413fec9685aElliott Hughes    dump_signal_info(log, tid, signal, si_code);
62520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
626053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
627df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris  UniquePtr<BacktraceMap> map(BacktraceMap::Create(pid));
628df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris  UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, tid, map.get()));
62920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  if (backtrace->Unwind(0)) {
63020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    dump_abort_message(backtrace.get(), log, abort_msg_address);
63184ddb34a3af77dbe490aaa07b738bbfd7109d5baChristopher Ferris    dump_thread(backtrace.get(), log);
63220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
633053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
63420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  if (want_logs) {
63522b5cef1277a5e1d5deef7420281eafade2e2614Mark Salyzyn    dump_logs(log, pid, 5);
63620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
6379846497f7926fc3240c2893d89e60880c22d1fd6Christopher Ferris
63820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  bool detach_failed = false;
63920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  if (dump_sibling_threads) {
640df2906186b6952c57b1f662bfef0b65c9f8c2e0dChristopher Ferris    detach_failed = dump_sibling_thread_report(log, pid, tid, total_sleep_time_usec, map.get());
64120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
642ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate
64320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  if (want_logs) {
64422b5cef1277a5e1d5deef7420281eafade2e2614Mark Salyzyn    dump_logs(log, pid, 0);
64520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
646053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
64720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  // send EOD to the Activity Manager, then wait for its ack to avoid racing ahead
64820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  // and killing the target out from under it
64920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  if (log->amfd >= 0) {
65020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    uint8_t eodMarker = 0;
65120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    TEMP_FAILURE_RETRY( write(log->amfd, &eodMarker, 1) );
65220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    // 3 sec timeout reading the ack; we're fine if that happens
65320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    TEMP_FAILURE_RETRY( read(log->amfd, &eodMarker, 1) );
65420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
655053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
65620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  return detach_failed;
65720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris}
658053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
65920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris// find_and_open_tombstone - find an available tombstone slot, if any, of the
66020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris// form tombstone_XX where XX is 00 to MAX_TOMBSTONES-1, inclusive. If no
66120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris// file is available, we reuse the least-recently-modified file.
66220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris//
66320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris// Returns the path of the tombstone file, allocated using malloc().  Caller must free() it.
66420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferrisstatic char* find_and_open_tombstone(int* fd) {
66568bd59f6d2c63b752aa4f38bcd655c0d52d6597eChristopher Ferris  // In a single pass, find an available slot and, in case none
66620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  // exist, find and record the least-recently-modified file.
66720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  char path[128];
66868bd59f6d2c63b752aa4f38bcd655c0d52d6597eChristopher Ferris  int oldest = -1;
66968bd59f6d2c63b752aa4f38bcd655c0d52d6597eChristopher Ferris  struct stat oldest_sb;
67020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  for (int i = 0; i < MAX_TOMBSTONES; i++) {
6714bb477205a2446c3ba9db8df0b0446173065d9ebKévin PETIT    snprintf(path, sizeof(path), TOMBSTONE_TEMPLATE, i);
67220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris
67368bd59f6d2c63b752aa4f38bcd655c0d52d6597eChristopher Ferris    struct stat sb;
67420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    if (!stat(path, &sb)) {
67568bd59f6d2c63b752aa4f38bcd655c0d52d6597eChristopher Ferris      if (oldest < 0 || sb.st_mtime < oldest_sb.st_mtime) {
67620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris        oldest = i;
67768bd59f6d2c63b752aa4f38bcd655c0d52d6597eChristopher Ferris        oldest_sb.st_mtime = sb.st_mtime;
67820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      }
67920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      continue;
68020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    }
68120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    if (errno != ENOENT)
68220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      continue;
68320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris
68404f9b2a809cb83c3d36c75791bfa28690800c883Nick Kralevich    *fd = open(path, O_CREAT | O_EXCL | O_WRONLY | O_NOFOLLOW | O_CLOEXEC, 0600);
68520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    if (*fd < 0)
68620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      continue;   // raced ?
687053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
688053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    fchown(*fd, AID_SYSTEM, AID_SYSTEM);
689053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    return strdup(path);
69020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
69120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris
69268bd59f6d2c63b752aa4f38bcd655c0d52d6597eChristopher Ferris  if (oldest < 0) {
69350eb546ec1584c04cf18f1941a042d7c5d045a67Brigid Smith    ALOGE("Failed to find a valid tombstone, default to using tombstone 0.\n");
69468bd59f6d2c63b752aa4f38bcd655c0d52d6597eChristopher Ferris    oldest = 0;
69568bd59f6d2c63b752aa4f38bcd655c0d52d6597eChristopher Ferris  }
69668bd59f6d2c63b752aa4f38bcd655c0d52d6597eChristopher Ferris
69720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  // we didn't find an available file, so we clobber the oldest one
6984bb477205a2446c3ba9db8df0b0446173065d9ebKévin PETIT  snprintf(path, sizeof(path), TOMBSTONE_TEMPLATE, oldest);
69904f9b2a809cb83c3d36c75791bfa28690800c883Nick Kralevich  *fd = open(path, O_CREAT | O_TRUNC | O_WRONLY | O_NOFOLLOW | O_CLOEXEC, 0600);
70020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  if (*fd < 0) {
70150eb546ec1584c04cf18f1941a042d7c5d045a67Brigid Smith    ALOGE("failed to open tombstone file '%s': %s\n", path, strerror(errno));
70220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    return NULL;
70320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
70420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  fchown(*fd, AID_SYSTEM, AID_SYSTEM);
70520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  return strdup(path);
706053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
707053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
708ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tatestatic int activity_manager_connect() {
70920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  int amfd = socket(PF_UNIX, SOCK_STREAM, 0);
71020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  if (amfd >= 0) {
71120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    struct sockaddr_un address;
71220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    int err;
71320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris
71420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    memset(&address, 0, sizeof(address));
71520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    address.sun_family = AF_UNIX;
71620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    strncpy(address.sun_path, NCRASH_SOCKET_PATH, sizeof(address.sun_path));
71720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    err = TEMP_FAILURE_RETRY(connect(
71820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris        amfd, reinterpret_cast<struct sockaddr*>(&address), sizeof(address)));
71920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    if (!err) {
72020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      struct timeval tv;
72120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      memset(&tv, 0, sizeof(tv));
72220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      tv.tv_sec = 1;  // tight leash
72320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      err = setsockopt(amfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
72420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      if (!err) {
72520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris        tv.tv_sec = 3;  // 3 seconds on handshake read
72620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris        err = setsockopt(amfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
72720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      }
72820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    }
72920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    if (err) {
73020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      close(amfd);
73120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris      amfd = -1;
732ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate    }
73320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
734ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate
73520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  return amfd;
736ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate}
737ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tate
738855fcc3114c20ff9fd286fe1723d1413fec9685aElliott Hugheschar* engrave_tombstone(pid_t pid, pid_t tid, int signal, int original_si_code,
73950eb546ec1584c04cf18f1941a042d7c5d045a67Brigid Smith                        uintptr_t abort_msg_address, bool dump_sibling_threads,
740855fcc3114c20ff9fd286fe1723d1413fec9685aElliott Hughes                        bool* detach_failed, int* total_sleep_time_usec) {
74162ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith
74262ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith  log_t log;
74362ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith  log.current_tid = tid;
74462ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith  log.crashed_tid = tid;
74562ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith
7464bb477205a2446c3ba9db8df0b0446173065d9ebKévin PETIT  if ((mkdir(TOMBSTONE_DIR, 0755) == -1) && (errno != EEXIST)) {
74750eb546ec1584c04cf18f1941a042d7c5d045a67Brigid Smith    _LOG(&log, logtype::ERROR, "failed to create %s: %s\n", TOMBSTONE_DIR, strerror(errno));
7484bb477205a2446c3ba9db8df0b0446173065d9ebKévin PETIT  }
7494bb477205a2446c3ba9db8df0b0446173065d9ebKévin PETIT
7504bb477205a2446c3ba9db8df0b0446173065d9ebKévin PETIT  if (chown(TOMBSTONE_DIR, AID_SYSTEM, AID_SYSTEM) == -1) {
75150eb546ec1584c04cf18f1941a042d7c5d045a67Brigid Smith    _LOG(&log, logtype::ERROR, "failed to change ownership of %s: %s\n", TOMBSTONE_DIR, strerror(errno));
7524bb477205a2446c3ba9db8df0b0446173065d9ebKévin PETIT  }
753053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
754c5bb49a138a78442e7326dfb6bbf85feadf0d486Christopher Ferris  int fd = -1;
755c5bb49a138a78442e7326dfb6bbf85feadf0d486Christopher Ferris  char* path = NULL;
756c5bb49a138a78442e7326dfb6bbf85feadf0d486Christopher Ferris  if (selinux_android_restorecon(TOMBSTONE_DIR, 0) == 0) {
757c5bb49a138a78442e7326dfb6bbf85feadf0d486Christopher Ferris    path = find_and_open_tombstone(&fd);
758c5bb49a138a78442e7326dfb6bbf85feadf0d486Christopher Ferris  } else {
75950eb546ec1584c04cf18f1941a042d7c5d045a67Brigid Smith    _LOG(&log, logtype::ERROR, "Failed to restore security context, not writing tombstone.\n");
76020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
761f1186f3e980f5ebcc3380d8a7f746bf8a45e3531rpcraig
76250eb546ec1584c04cf18f1941a042d7c5d045a67Brigid Smith  if (fd < 0) {
76350eb546ec1584c04cf18f1941a042d7c5d045a67Brigid Smith    _LOG(&log, logtype::ERROR, "Skipping tombstone write, nothing to do.\n");
76420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    *detach_failed = false;
76520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris    return NULL;
76620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  }
767053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
76820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  log.tfd = fd;
769c5bb49a138a78442e7326dfb6bbf85feadf0d486Christopher Ferris  // Preserve amfd since it can be modified through the calls below without
770c5bb49a138a78442e7326dfb6bbf85feadf0d486Christopher Ferris  // being closed.
771c5bb49a138a78442e7326dfb6bbf85feadf0d486Christopher Ferris  int amfd = activity_manager_connect();
772c5bb49a138a78442e7326dfb6bbf85feadf0d486Christopher Ferris  log.amfd = amfd;
773855fcc3114c20ff9fd286fe1723d1413fec9685aElliott Hughes  *detach_failed = dump_crash(&log, pid, tid, signal, original_si_code, abort_msg_address,
774855fcc3114c20ff9fd286fe1723d1413fec9685aElliott Hughes                              dump_sibling_threads, total_sleep_time_usec);
775053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
77662ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith  ALOGI("\nTombstone written to: %s\n", path);
77762ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith
778c5bb49a138a78442e7326dfb6bbf85feadf0d486Christopher Ferris  // Either of these file descriptors can be -1, any error is ignored.
779c5bb49a138a78442e7326dfb6bbf85feadf0d486Christopher Ferris  close(amfd);
78020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  close(fd);
781c5bb49a138a78442e7326dfb6bbf85feadf0d486Christopher Ferris
78220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris  return path;
783053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
784