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