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