debuggerd.c revision 13e715b491e876865e752a3a69dd6f347049a488
1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* system/debuggerd/debuggerd.c 2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** 3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Copyright 2006, The Android Open Source Project 4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** 509e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng** Licensed under the Apache License, Version 2.0 (the "License"); 609e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng** you may not use this file except in compliance with the License. 709e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng** You may obtain a copy of the License at 8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** 909e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng** http://www.apache.org/licenses/LICENSE-2.0 10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** 1109e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng** Unless required by applicable law or agreed to in writing, software 1209e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng** distributed under the License is distributed on an "AS IS" BASIS, 1309e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1409e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng** See the License for the specific language governing permissions and 15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** limitations under the License. 16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project*/ 17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h> 19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h> 20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <signal.h> 21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <pthread.h> 22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdarg.h> 23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <fcntl.h> 24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h> 25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <dirent.h> 26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/ptrace.h> 28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/wait.h> 29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/exec_elf.h> 30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/stat.h> 31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/sockets.h> 33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/logd.h> 3441e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden#include <cutils/logger.h> 35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/properties.h> 36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 3713e715b491e876865e752a3a69dd6f347049a488Jeff Brown#include <corkscrew/backtrace.h> 3813e715b491e876865e752a3a69dd6f347049a488Jeff Brown 39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/input.h> 40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <private/android_filesystem_config.h> 42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 4313e715b491e876865e752a3a69dd6f347049a488Jeff Brown#include "getevent.h" 4413e715b491e876865e752a3a69dd6f347049a488Jeff Brown#include "machine.h" 45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "utility.h" 46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define ANDROID_LOG_INFO 4 48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 4913e715b491e876865e752a3a69dd6f347049a488Jeff Brownstatic void dump_build_info(int tfd) 50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char fingerprint[PROPERTY_VALUE_MAX]; 52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project property_get("ro.build.fingerprint", fingerprint, "unknown"); 54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project _LOG(tfd, false, "Build fingerprint: '%s'\n", fingerprint); 56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 5813e715b491e876865e752a3a69dd6f347049a488Jeff Brownstatic const char *get_signame(int sig) 59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project switch(sig) { 61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case SIGILL: return "SIGILL"; 62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case SIGABRT: return "SIGABRT"; 63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case SIGBUS: return "SIGBUS"; 64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case SIGFPE: return "SIGFPE"; 65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case SIGSEGV: return "SIGSEGV"; 66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case SIGSTKFLT: return "SIGSTKFLT"; 67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project default: return "?"; 68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 7113e715b491e876865e752a3a69dd6f347049a488Jeff Brownstatic const char *get_sigcode(int signo, int code) 7283c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro{ 7383c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro switch (signo) { 7483c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro case SIGILL: 7583c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro switch (code) { 7683c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro case ILL_ILLOPC: return "ILL_ILLOPC"; 7783c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro case ILL_ILLOPN: return "ILL_ILLOPN"; 7883c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro case ILL_ILLADR: return "ILL_ILLADR"; 7983c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro case ILL_ILLTRP: return "ILL_ILLTRP"; 8083c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro case ILL_PRVOPC: return "ILL_PRVOPC"; 8183c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro case ILL_PRVREG: return "ILL_PRVREG"; 8283c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro case ILL_COPROC: return "ILL_COPROC"; 8383c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro case ILL_BADSTK: return "ILL_BADSTK"; 8483c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro } 8583c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro break; 8683c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro case SIGBUS: 8783c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro switch (code) { 8883c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro case BUS_ADRALN: return "BUS_ADRALN"; 8983c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro case BUS_ADRERR: return "BUS_ADRERR"; 9083c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro case BUS_OBJERR: return "BUS_OBJERR"; 9183c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro } 9283c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro break; 9383c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro case SIGFPE: 9483c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro switch (code) { 9583c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro case FPE_INTDIV: return "FPE_INTDIV"; 9683c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro case FPE_INTOVF: return "FPE_INTOVF"; 9783c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro case FPE_FLTDIV: return "FPE_FLTDIV"; 9883c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro case FPE_FLTOVF: return "FPE_FLTOVF"; 9983c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro case FPE_FLTUND: return "FPE_FLTUND"; 10083c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro case FPE_FLTRES: return "FPE_FLTRES"; 10183c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro case FPE_FLTINV: return "FPE_FLTINV"; 10283c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro case FPE_FLTSUB: return "FPE_FLTSUB"; 10383c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro } 10483c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro break; 10583c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro case SIGSEGV: 10683c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro switch (code) { 10783c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro case SEGV_MAPERR: return "SEGV_MAPERR"; 10883c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro case SEGV_ACCERR: return "SEGV_ACCERR"; 10983c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro } 11083c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro break; 11183c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro } 11283c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro return "?"; 11383c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro} 11483c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro 11513e715b491e876865e752a3a69dd6f347049a488Jeff Brownstatic void dump_fault_addr(int tfd, pid_t pid, int sig) 116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project siginfo_t si; 11809e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng 119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(&si, 0, sizeof(si)); 120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(ptrace(PTRACE_GETSIGINFO, pid, 0, &si)){ 121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project _LOG(tfd, false, "cannot get siginfo: %s\n", strerror(errno)); 122136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden } else if (signal_has_address(sig)) { 12383c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro _LOG(tfd, false, "signal %d (%s), code %d (%s), fault addr %08x\n", 12483c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro sig, get_signame(sig), 12583c6b052918178033875e7ea54ca746cf7303f87Carl Shapiro si.si_code, get_sigcode(sig, si.si_code), 126e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden (uintptr_t) si.si_addr); 127136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden } else { 128136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden _LOG(tfd, false, "signal %d (%s), code %d (%s), fault addr --------\n", 129136dcc5ce628a1ba600a6818e5cb24d5f15eb016Andy McFadden sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code)); 130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 13313e715b491e876865e752a3a69dd6f347049a488Jeff Brownstatic void dump_crash_banner(int tfd, pid_t pid, pid_t tid, int sig) 134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char data[1024]; 136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char *x = 0; 137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project FILE *fp; 13809e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng 139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sprintf(data, "/proc/%d/cmdline", pid); 140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fp = fopen(data, "r"); 141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fp) { 142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project x = fgets(data, 1024, fp); 143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fclose(fp); 144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 14509e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng 146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project _LOG(tfd, false, 14713e715b491e876865e752a3a69dd6f347049a488Jeff Brown "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"); 148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project dump_build_info(tfd); 149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project _LOG(tfd, false, "pid: %d, tid: %d >>> %s <<<\n", 150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project pid, tid, x ? x : "UNKNOWN"); 15109e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng 15213e715b491e876865e752a3a69dd6f347049a488Jeff Brown if(sig) { 15313e715b491e876865e752a3a69dd6f347049a488Jeff Brown dump_fault_addr(tfd, tid, sig); 154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* Return true if some thread is not detached cleanly */ 15813e715b491e876865e752a3a69dd6f347049a488Jeff Brownstatic bool dump_sibling_thread_report(ptrace_context_t* context, 15913e715b491e876865e752a3a69dd6f347049a488Jeff Brown int tfd, pid_t pid, pid_t tid) 160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char task_path[1024]; 162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sprintf(task_path, "/proc/%d/task", pid); 164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project DIR *d; 165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct dirent *de; 166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int need_cleanup = 0; 167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project d = opendir(task_path); 169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* Bail early if cannot open the task directory */ 170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (d == NULL) { 171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project XLOG("Cannot open /proc/%d/task\n", pid); 172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return false; 173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while ((de = readdir(d)) != NULL) { 17513e715b491e876865e752a3a69dd6f347049a488Jeff Brown pid_t new_tid; 176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* Ignore "." and ".." */ 17709e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) 178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project continue; 179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project new_tid = atoi(de->d_name); 180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* The main thread at fault has been handled individually */ 181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (new_tid == tid) 182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project continue; 183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* Skip this thread if cannot ptrace it */ 185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ptrace(PTRACE_ATTACH, new_tid, 0, 0) < 0) 186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project continue; 187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 18813e715b491e876865e752a3a69dd6f347049a488Jeff Brown _LOG(tfd, true, 18913e715b491e876865e752a3a69dd6f347049a488Jeff Brown "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n"); 19013e715b491e876865e752a3a69dd6f347049a488Jeff Brown _LOG(tfd, true, "pid: %d, tid: %d\n", pid, new_tid); 19113e715b491e876865e752a3a69dd6f347049a488Jeff Brown 19213e715b491e876865e752a3a69dd6f347049a488Jeff Brown dump_thread(context, tfd, new_tid, false); 193e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden 194e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden if (ptrace(PTRACE_DETACH, new_tid, 0, 0) != 0) { 195e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden XLOG("detach of tid %d failed: %s\n", new_tid, strerror(errno)); 196e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden need_cleanup = 1; 197e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden } 198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project closedir(d); 200e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden 201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return need_cleanup != 0; 202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 20441e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden/* 20541e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden * Reads the contents of the specified log device, filters out the entries 20641e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden * that don't match the specified pid, and writes them to the tombstone file. 207e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden * 208e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden * If "tailOnly" is set, we only print the last few lines. 20941e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden */ 21013e715b491e876865e752a3a69dd6f347049a488Jeff Brownstatic void dump_log_file(int tfd, pid_t pid, const char* filename, 211e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden bool tailOnly) 21241e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden{ 213e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden bool first = true; 214e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden 215e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden /* circular buffer, for "tailOnly" mode */ 216e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden const int kShortLogMaxLines = 5; 217e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden const int kShortLogLineLen = 256; 218e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden char shortLog[kShortLogMaxLines][kShortLogLineLen]; 219e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden int shortLogCount = 0; 220e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden int shortLogNext = 0; 221e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden 22241e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden int logfd = open(filename, O_RDONLY | O_NONBLOCK); 22341e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden if (logfd < 0) { 22441e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden XLOG("Unable to open %s: %s\n", filename, strerror(errno)); 22541e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden return; 22641e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden } 22741e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden 22841e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden union { 22941e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1]; 23041e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden struct logger_entry entry; 23141e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden } log_entry; 23241e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden 23341e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden while (true) { 23441e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden ssize_t actual = read(logfd, log_entry.buf, LOGGER_ENTRY_MAX_LEN); 23541e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden if (actual < 0) { 23641e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden if (errno == EINTR) { 23741e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden /* interrupted by signal, retry */ 23841e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden continue; 23941e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden } else if (errno == EAGAIN) { 24041e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden /* non-blocking EOF; we're done */ 24141e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden break; 24241e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden } else { 24341e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden _LOG(tfd, true, "Error while reading log: %s\n", 24441e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden strerror(errno)); 24541e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden break; 24641e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden } 24741e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden } else if (actual == 0) { 24841e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden _LOG(tfd, true, "Got zero bytes while reading log: %s\n", 24941e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden strerror(errno)); 25041e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden break; 25141e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden } 25241e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden 25341e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden /* 25441e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden * NOTE: if you XLOG something here, this will spin forever, 25541e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden * because you will be writing as fast as you're reading. Any 25641e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden * high-frequency debug diagnostics should just be written to 25741e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden * the tombstone file. 25841e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden */ 25941e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden 26041e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden struct logger_entry* entry = &log_entry.entry; 26141e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden 26241e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden if (entry->pid != (int32_t) pid) { 26341e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden /* wrong pid, ignore */ 26441e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden continue; 26541e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden } 26641e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden 267e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden if (first) { 268e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden _LOG(tfd, true, "--------- %slog %s\n", 269e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden tailOnly ? "tail end of " : "", filename); 270e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden first = false; 271e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden } 272e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden 27341e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden /* 27441e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden * Msg format is: <priority:1><tag:N>\0<message:N>\0 27541e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden * 27641e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden * We want to display it in the same format as "logcat -v threadtime" 27741e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden * (although in this case the pid is redundant). 27841e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden * 27941e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden * TODO: scan for line breaks ('\n') and display each text line 28041e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden * on a separate line, prefixed with the header, like logcat does. 28141e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden */ 28241e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden static const char* kPrioChars = "!.VDIWEFS"; 28341e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden unsigned char prio = entry->msg[0]; 284e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden char* tag = entry->msg + 1; 285e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden char* msg = tag + strlen(tag) + 1; 286e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden 287e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden /* consume any trailing newlines */ 288e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden char* eatnl = msg + strlen(msg) - 1; 289e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden while (eatnl >= msg && *eatnl == '\n') { 290e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden *eatnl-- = '\0'; 291e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden } 29241e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden 293e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden char prioChar = (prio < strlen(kPrioChars) ? kPrioChars[prio] : '?'); 29441e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden 29541e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden char timeBuf[32]; 29641e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden time_t sec = (time_t) entry->sec; 29741e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden struct tm tmBuf; 29841e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden struct tm* ptm; 29941e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden ptm = localtime_r(&sec, &tmBuf); 30041e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", ptm); 30141e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden 302e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden if (tailOnly) { 303e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden snprintf(shortLog[shortLogNext], kShortLogLineLen, 304e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden "%s.%03d %5d %5d %c %-8s: %s", 305e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden timeBuf, entry->nsec / 1000000, entry->pid, entry->tid, 306e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden prioChar, tag, msg); 307e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden shortLogNext = (shortLogNext + 1) % kShortLogMaxLines; 308e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden shortLogCount++; 309e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden } else { 310e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden _LOG(tfd, true, "%s.%03d %5d %5d %c %-8s: %s\n", 311e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden timeBuf, entry->nsec / 1000000, entry->pid, entry->tid, 312e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden prioChar, tag, msg); 313e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden } 314e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden } 315e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden 316e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden if (tailOnly) { 317e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden int i; 318e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden 319e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden /* 320e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden * If we filled the buffer, we want to start at "next", which has 321e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden * the oldest entry. If we didn't, we want to start at zero. 322e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden */ 323e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden if (shortLogCount < kShortLogMaxLines) { 324e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden shortLogNext = 0; 325e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden } else { 326e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden shortLogCount = kShortLogMaxLines; /* cap at window size */ 327e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden } 328e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden 329e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden for (i = 0; i < shortLogCount; i++) { 330e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden _LOG(tfd, true, "%s\n", shortLog[shortLogNext]); 331e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden shortLogNext = (shortLogNext + 1) % kShortLogMaxLines; 332e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden } 33341e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden } 33441e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden 33541e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden close(logfd); 33641e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden} 33741e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden 33841e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden/* 33941e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden * Dumps the logs generated by the specified pid to the tombstone, from both 34041e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden * "system" and "main" log devices. Ideally we'd interleave the output. 34141e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden */ 34213e715b491e876865e752a3a69dd6f347049a488Jeff Brownstatic void dump_logs(int tfd, pid_t pid, bool tailOnly) 34341e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden{ 344e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden dump_log_file(tfd, pid, "/dev/log/system", tailOnly); 345e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden dump_log_file(tfd, pid, "/dev/log/main", tailOnly); 34641e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden} 34741e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden 34813e715b491e876865e752a3a69dd6f347049a488Jeff Brown/* 34913e715b491e876865e752a3a69dd6f347049a488Jeff Brown * Dumps all information about the specified pid to the tombstone. 35013e715b491e876865e752a3a69dd6f347049a488Jeff Brown */ 35113e715b491e876865e752a3a69dd6f347049a488Jeff Brownstatic bool dump_crash(int tfd, pid_t pid, pid_t tid, int signal, 35213e715b491e876865e752a3a69dd6f347049a488Jeff Brown bool dump_sibling_threads) 353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 354e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden /* don't copy log messages to tombstone unless this is a dev device */ 355e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden char value[PROPERTY_VALUE_MAX]; 356e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden property_get("ro.debuggable", value, "0"); 357e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden bool wantLogs = (value[0] == '1'); 35813e715b491e876865e752a3a69dd6f347049a488Jeff Brown bool need_cleanup = false; 359e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden 36013e715b491e876865e752a3a69dd6f347049a488Jeff Brown dump_crash_banner(tfd, pid, tid, signal); 361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 36213e715b491e876865e752a3a69dd6f347049a488Jeff Brown ptrace_context_t* context = load_ptrace_context(pid); 363dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 36413e715b491e876865e752a3a69dd6f347049a488Jeff Brown dump_thread(context, tfd, tid, true); 365e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden 366e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden if (wantLogs) { 36713e715b491e876865e752a3a69dd6f347049a488Jeff Brown dump_logs(tfd, pid, true); 368e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden } 369e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden 37013e715b491e876865e752a3a69dd6f347049a488Jeff Brown if (dump_sibling_threads) { 37113e715b491e876865e752a3a69dd6f347049a488Jeff Brown need_cleanup = dump_sibling_thread_report(context, tfd, pid, tid); 372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 37413e715b491e876865e752a3a69dd6f347049a488Jeff Brown free_ptrace_context(context); 37513e715b491e876865e752a3a69dd6f347049a488Jeff Brown 376e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden if (wantLogs) { 37713e715b491e876865e752a3a69dd6f347049a488Jeff Brown dump_logs(tfd, pid, false); 37841e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden } 37913e715b491e876865e752a3a69dd6f347049a488Jeff Brown return need_cleanup; 38013e715b491e876865e752a3a69dd6f347049a488Jeff Brown} 38113e715b491e876865e752a3a69dd6f347049a488Jeff Brown 38213e715b491e876865e752a3a69dd6f347049a488Jeff Brown#define MAX_TOMBSTONES 10 38313e715b491e876865e752a3a69dd6f347049a488Jeff Brown 38413e715b491e876865e752a3a69dd6f347049a488Jeff Brown#define typecheck(x,y) { \ 38513e715b491e876865e752a3a69dd6f347049a488Jeff Brown typeof(x) __dummy1; \ 38613e715b491e876865e752a3a69dd6f347049a488Jeff Brown typeof(y) __dummy2; \ 38713e715b491e876865e752a3a69dd6f347049a488Jeff Brown (void)(&__dummy1 == &__dummy2); } 38813e715b491e876865e752a3a69dd6f347049a488Jeff Brown 38913e715b491e876865e752a3a69dd6f347049a488Jeff Brown#define TOMBSTONE_DIR "/data/tombstones" 39013e715b491e876865e752a3a69dd6f347049a488Jeff Brown 39113e715b491e876865e752a3a69dd6f347049a488Jeff Brown/* 39213e715b491e876865e752a3a69dd6f347049a488Jeff Brown * find_and_open_tombstone - find an available tombstone slot, if any, of the 39313e715b491e876865e752a3a69dd6f347049a488Jeff Brown * form tombstone_XX where XX is 00 to MAX_TOMBSTONES-1, inclusive. If no 39413e715b491e876865e752a3a69dd6f347049a488Jeff Brown * file is available, we reuse the least-recently-modified file. 39513e715b491e876865e752a3a69dd6f347049a488Jeff Brown */ 39613e715b491e876865e752a3a69dd6f347049a488Jeff Brownstatic int find_and_open_tombstone(void) 39713e715b491e876865e752a3a69dd6f347049a488Jeff Brown{ 39813e715b491e876865e752a3a69dd6f347049a488Jeff Brown unsigned long mtime = ULONG_MAX; 39913e715b491e876865e752a3a69dd6f347049a488Jeff Brown struct stat sb; 40013e715b491e876865e752a3a69dd6f347049a488Jeff Brown char path[128]; 40113e715b491e876865e752a3a69dd6f347049a488Jeff Brown int fd, i, oldest = 0; 40213e715b491e876865e752a3a69dd6f347049a488Jeff Brown 40313e715b491e876865e752a3a69dd6f347049a488Jeff Brown /* 40413e715b491e876865e752a3a69dd6f347049a488Jeff Brown * XXX: Our stat.st_mtime isn't time_t. If it changes, as it probably ought 40513e715b491e876865e752a3a69dd6f347049a488Jeff Brown * to, our logic breaks. This check will generate a warning if that happens. 40613e715b491e876865e752a3a69dd6f347049a488Jeff Brown */ 40713e715b491e876865e752a3a69dd6f347049a488Jeff Brown typecheck(mtime, sb.st_mtime); 40813e715b491e876865e752a3a69dd6f347049a488Jeff Brown 40913e715b491e876865e752a3a69dd6f347049a488Jeff Brown /* 41013e715b491e876865e752a3a69dd6f347049a488Jeff Brown * In a single wolf-like pass, find an available slot and, in case none 41113e715b491e876865e752a3a69dd6f347049a488Jeff Brown * exist, find and record the least-recently-modified file. 41213e715b491e876865e752a3a69dd6f347049a488Jeff Brown */ 41313e715b491e876865e752a3a69dd6f347049a488Jeff Brown for (i = 0; i < MAX_TOMBSTONES; i++) { 41413e715b491e876865e752a3a69dd6f347049a488Jeff Brown snprintf(path, sizeof(path), TOMBSTONE_DIR"/tombstone_%02d", i); 41513e715b491e876865e752a3a69dd6f347049a488Jeff Brown 41613e715b491e876865e752a3a69dd6f347049a488Jeff Brown if (!stat(path, &sb)) { 41713e715b491e876865e752a3a69dd6f347049a488Jeff Brown if (sb.st_mtime < mtime) { 41813e715b491e876865e752a3a69dd6f347049a488Jeff Brown oldest = i; 41913e715b491e876865e752a3a69dd6f347049a488Jeff Brown mtime = sb.st_mtime; 42013e715b491e876865e752a3a69dd6f347049a488Jeff Brown } 42113e715b491e876865e752a3a69dd6f347049a488Jeff Brown continue; 42213e715b491e876865e752a3a69dd6f347049a488Jeff Brown } 42313e715b491e876865e752a3a69dd6f347049a488Jeff Brown if (errno != ENOENT) 42413e715b491e876865e752a3a69dd6f347049a488Jeff Brown continue; 42513e715b491e876865e752a3a69dd6f347049a488Jeff Brown 42613e715b491e876865e752a3a69dd6f347049a488Jeff Brown fd = open(path, O_CREAT | O_EXCL | O_WRONLY, 0600); 42713e715b491e876865e752a3a69dd6f347049a488Jeff Brown if (fd < 0) 42813e715b491e876865e752a3a69dd6f347049a488Jeff Brown continue; /* raced ? */ 42913e715b491e876865e752a3a69dd6f347049a488Jeff Brown 43013e715b491e876865e752a3a69dd6f347049a488Jeff Brown fchown(fd, AID_SYSTEM, AID_SYSTEM); 43113e715b491e876865e752a3a69dd6f347049a488Jeff Brown return fd; 43213e715b491e876865e752a3a69dd6f347049a488Jeff Brown } 43313e715b491e876865e752a3a69dd6f347049a488Jeff Brown 43413e715b491e876865e752a3a69dd6f347049a488Jeff Brown /* we didn't find an available file, so we clobber the oldest one */ 43513e715b491e876865e752a3a69dd6f347049a488Jeff Brown snprintf(path, sizeof(path), TOMBSTONE_DIR"/tombstone_%02d", oldest); 43613e715b491e876865e752a3a69dd6f347049a488Jeff Brown fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600); 43713e715b491e876865e752a3a69dd6f347049a488Jeff Brown fchown(fd, AID_SYSTEM, AID_SYSTEM); 43813e715b491e876865e752a3a69dd6f347049a488Jeff Brown 43913e715b491e876865e752a3a69dd6f347049a488Jeff Brown return fd; 44013e715b491e876865e752a3a69dd6f347049a488Jeff Brown} 44113e715b491e876865e752a3a69dd6f347049a488Jeff Brown 44213e715b491e876865e752a3a69dd6f347049a488Jeff Brown/* Return true if some thread is not detached cleanly */ 44313e715b491e876865e752a3a69dd6f347049a488Jeff Brownstatic bool engrave_tombstone(pid_t pid, pid_t tid, int signal, 44413e715b491e876865e752a3a69dd6f347049a488Jeff Brown bool dump_sibling_threads) 44513e715b491e876865e752a3a69dd6f347049a488Jeff Brown{ 44613e715b491e876865e752a3a69dd6f347049a488Jeff Brown int fd; 44713e715b491e876865e752a3a69dd6f347049a488Jeff Brown bool need_cleanup = false; 44813e715b491e876865e752a3a69dd6f347049a488Jeff Brown 44913e715b491e876865e752a3a69dd6f347049a488Jeff Brown mkdir(TOMBSTONE_DIR, 0755); 45013e715b491e876865e752a3a69dd6f347049a488Jeff Brown chown(TOMBSTONE_DIR, AID_SYSTEM, AID_SYSTEM); 45113e715b491e876865e752a3a69dd6f347049a488Jeff Brown 45213e715b491e876865e752a3a69dd6f347049a488Jeff Brown fd = find_and_open_tombstone(); 45313e715b491e876865e752a3a69dd6f347049a488Jeff Brown if (fd < 0) 45413e715b491e876865e752a3a69dd6f347049a488Jeff Brown return need_cleanup; 45513e715b491e876865e752a3a69dd6f347049a488Jeff Brown 45613e715b491e876865e752a3a69dd6f347049a488Jeff Brown need_cleanup = dump_crash(fd, pid, tid, signal, dump_sibling_threads); 45741e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden 458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fd); 459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return need_cleanup; 460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int 463dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectwrite_string(const char* file, const char* string) 464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int len; 466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int fd; 467dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ssize_t amt; 468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd = open(file, O_RDWR); 469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project len = strlen(string); 470dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (fd < 0) 471dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -errno; 472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project amt = write(fd, string, len); 473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fd); 474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return amt >= 0 ? 0 : -errno; 475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic 478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid init_debug_led(void) 479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // trout leds 481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project write_string("/sys/class/leds/red/brightness", "0"); 482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project write_string("/sys/class/leds/green/brightness", "0"); 483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project write_string("/sys/class/leds/blue/brightness", "0"); 484dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project write_string("/sys/class/leds/red/device/blink", "0"); 485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // sardine leds 486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project write_string("/sys/class/leds/left/cadence", "0,0"); 487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 488dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 489dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic 490dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid enable_debug_led(void) 491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // trout leds 493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project write_string("/sys/class/leds/red/brightness", "255"); 494dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // sardine leds 495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project write_string("/sys/class/leds/left/cadence", "1,0"); 496dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 497dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 498dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic 499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid disable_debug_led(void) 500dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // trout leds 502dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project write_string("/sys/class/leds/red/brightness", "0"); 503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // sardine leds 504dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project write_string("/sys/class/leds/left/cadence", "0,0"); 505dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 506dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 50713e715b491e876865e752a3a69dd6f347049a488Jeff Brownstatic void wait_for_user_action(pid_t tid, struct ucred* cr) 508dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 509dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project (void)tid; 510dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* First log a helpful message */ 511dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG( "********************************************************\n" 5123bfdcc979da0f857b014318f3df5d95a0f93eb27Andy McFadden "* Process %d has been suspended while crashing. To\n" 5133bfdcc979da0f857b014318f3df5d95a0f93eb27Andy McFadden "* attach gdbserver for a gdb connection on port 5039:\n" 5143bfdcc979da0f857b014318f3df5d95a0f93eb27Andy McFadden "*\n" 5153bfdcc979da0f857b014318f3df5d95a0f93eb27Andy McFadden "* adb shell gdbserver :5039 --attach %d &\n" 5163bfdcc979da0f857b014318f3df5d95a0f93eb27Andy McFadden "*\n" 5173bfdcc979da0f857b014318f3df5d95a0f93eb27Andy McFadden "* Press HOME key to let the process continue crashing.\n" 51809e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng "********************************************************\n", 519dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project cr->pid, cr->pid); 520dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 5213bfdcc979da0f857b014318f3df5d95a0f93eb27Andy McFadden /* wait for HOME key (TODO: something useful for devices w/o HOME key) */ 522dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (init_getevent() == 0) { 523dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int ms = 1200 / 10; 524dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int dit = 1; 525dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int dah = 3*dit; 526dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int _ = -dit; 527dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int ___ = 3*_; 528dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int _______ = 7*_; 529dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project const signed char codes[] = { 530dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project dit,_,dit,_,dit,___,dah,_,dah,_,dah,___,dit,_,dit,_,dit,_______ 531dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project }; 532dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project size_t s = 0; 533dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct input_event e; 534dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int home = 0; 535dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project init_debug_led(); 536dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project enable_debug_led(); 537dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project do { 538dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int timeout = abs((int)(codes[s])) * ms; 539dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int res = get_event(&e, timeout); 540dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (res == 0) { 541dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (e.type==EV_KEY && e.code==KEY_HOME && e.value==0) 542dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project home = 1; 543dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else if (res == 1) { 544dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (++s >= sizeof(codes)/sizeof(*codes)) 545dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project s = 0; 546dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (codes[s] > 0) { 547dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project enable_debug_led(); 548dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 549dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project disable_debug_led(); 550dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 551dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 55209e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng } while (!home); 553dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project uninit_getevent(); 554dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 555dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 556dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* don't forget to turn debug led off */ 557dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project disable_debug_led(); 55809e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng 559dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* close filedescriptor */ 560dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG("debuggerd resuming process %d", cr->pid); 561dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 562dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 563dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void handle_crashing_process(int fd) 564dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 565dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char buf[64]; 566dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct stat s; 56713e715b491e876865e752a3a69dd6f347049a488Jeff Brown pid_t tid; 568dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ucred cr; 56909e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng int n, len, status; 570dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int tid_attach_status = -1; 571dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned retry = 30; 572dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bool need_cleanup = false; 573dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 57413e715b491e876865e752a3a69dd6f347049a488Jeff Brown XLOG("handle_crashing_process(%d)\n", fd); 57513e715b491e876865e752a3a69dd6f347049a488Jeff Brown 576dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char value[PROPERTY_VALUE_MAX]; 577dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project property_get("debug.db.uid", value, "-1"); 578dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int debug_uid = atoi(value); 57909e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng 580dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project len = sizeof(cr); 581dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project n = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &len); 582dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(n != 0) { 583dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG("cannot get credentials\n"); 584dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto done; 585dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 586dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 58709e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng XLOG("reading tid\n"); 588dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fcntl(fd, F_SETFL, O_NONBLOCK); 58913e715b491e876865e752a3a69dd6f347049a488Jeff Brown while((n = read(fd, &tid, sizeof(pid_t))) != sizeof(pid_t)) { 590dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(errno == EINTR) continue; 591dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(errno == EWOULDBLOCK) { 592dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(retry-- > 0) { 593dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project usleep(100 * 1000); 594dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project continue; 595dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 596dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG("timed out reading tid\n"); 597dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto done; 598dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 599dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG("read failure? %s\n", strerror(errno)); 600dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto done; 601dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 602dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 60302526d486803de153d03851f4d5f9be7c555e46cDavid 'Digit' Turner snprintf(buf, sizeof buf, "/proc/%d/task/%d", cr.pid, tid); 604dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(stat(buf, &s)) { 6053bfdcc979da0f857b014318f3df5d95a0f93eb27Andy McFadden LOG("tid %d does not exist in pid %d. ignoring debug request\n", 606dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project tid, cr.pid); 607dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fd); 608dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return; 609dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 61009e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng 611dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project XLOG("BOOM: pid=%d uid=%d gid=%d tid=%d\n", cr.pid, cr.uid, cr.gid, tid); 612dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 61313e715b491e876865e752a3a69dd6f347049a488Jeff Brown /* 61413e715b491e876865e752a3a69dd6f347049a488Jeff Brown * If the user has requested to attach gdb, don't collect the per-thread 61513e715b491e876865e752a3a69dd6f347049a488Jeff Brown * information as it increases the chance to lose track of the process. 61613e715b491e876865e752a3a69dd6f347049a488Jeff Brown */ 61713e715b491e876865e752a3a69dd6f347049a488Jeff Brown bool dump_sibling_threads = (signed)cr.pid > debug_uid; 61813e715b491e876865e752a3a69dd6f347049a488Jeff Brown 61902526d486803de153d03851f4d5f9be7c555e46cDavid 'Digit' Turner /* Note that at this point, the target thread's signal handler 62002526d486803de153d03851f4d5f9be7c555e46cDavid 'Digit' Turner * is blocked in a read() call. This gives us the time to PTRACE_ATTACH 62102526d486803de153d03851f4d5f9be7c555e46cDavid 'Digit' Turner * to it before it has a chance to really fault. 62202526d486803de153d03851f4d5f9be7c555e46cDavid 'Digit' Turner * 623e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden * The PTRACE_ATTACH sends a SIGSTOP to the target process, but it 624e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden * won't necessarily have stopped by the time ptrace() returns. (We 625e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden * currently assume it does.) We write to the file descriptor to 626e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden * ensure that it can run as soon as we call PTRACE_CONT below. 627e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden * See details in bionic/libc/linker/debugger.c, in function 62802526d486803de153d03851f4d5f9be7c555e46cDavid 'Digit' Turner * debugger_signal_handler(). 62902526d486803de153d03851f4d5f9be7c555e46cDavid 'Digit' Turner */ 630dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project tid_attach_status = ptrace(PTRACE_ATTACH, tid, 0, 0); 631655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden int ptrace_error = errno; 63202526d486803de153d03851f4d5f9be7c555e46cDavid 'Digit' Turner 633655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden if (TEMP_FAILURE_RETRY(write(fd, &tid, 1)) != 1) { 634655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden XLOG("failed responding to client: %s\n", 635655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden strerror(errno)); 636655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden goto done; 637655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden } 63802526d486803de153d03851f4d5f9be7c555e46cDavid 'Digit' Turner 639dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(tid_attach_status < 0) { 640655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden LOG("ptrace attach failed: %s\n", strerror(ptrace_error)); 641dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto done; 642dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 643dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 644dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fd); 645dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd = -1; 646dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 647655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden const int sleep_time_usec = 200000; /* 0.2 seconds */ 648655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden const int max_total_sleep_usec = 3000000; /* 3 seconds */ 649655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden int loop_limit = max_total_sleep_usec / sleep_time_usec; 650dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for(;;) { 651655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden if (loop_limit-- == 0) { 652655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden LOG("timed out waiting for pid=%d tid=%d uid=%d to die\n", 653655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden cr.pid, tid, cr.uid); 654655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden goto done; 655655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden } 656655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden n = waitpid(tid, &status, __WALL | WNOHANG); 657655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden 658655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden if (n == 0) { 659655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden /* not ready yet */ 660655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden XLOG("not ready yet\n"); 661655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden usleep(sleep_time_usec); 662655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden continue; 663655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden } 66409e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng 665dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(n < 0) { 666dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(errno == EAGAIN) continue; 667dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG("waitpid failed: %s\n", strerror(errno)); 668dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto done; 669dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 670dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 671dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project XLOG("waitpid: n=%d status=%08x\n", n, status); 672dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 673dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(WIFSTOPPED(status)){ 674dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project n = WSTOPSIG(status); 675dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project switch(n) { 676dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case SIGSTOP: 677dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project XLOG("stopped -- continuing\n"); 678dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project n = ptrace(PTRACE_CONT, tid, 0, 0); 679dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(n) { 680dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG("ptrace failed: %s\n", strerror(errno)); 681dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto done; 682dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 683dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project continue; 68409e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng 685dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case SIGILL: 686dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case SIGABRT: 687dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case SIGBUS: 688dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case SIGFPE: 689dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case SIGSEGV: 690dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project case SIGSTKFLT: { 691dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project XLOG("stopped -- fatal signal\n"); 69213e715b491e876865e752a3a69dd6f347049a488Jeff Brown need_cleanup = engrave_tombstone(cr.pid, tid, n, 69313e715b491e876865e752a3a69dd6f347049a488Jeff Brown dump_sibling_threads); 694dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project kill(tid, SIGSTOP); 695dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto done; 696dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 697dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 698dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project default: 699dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project XLOG("stopped -- unexpected signal\n"); 700dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto done; 701dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 702dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 703dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project XLOG("unexpected waitpid response\n"); 704dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project goto done; 705dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 706dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 70709e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng 708dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectdone: 709dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project XLOG("detaching\n"); 71009e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng 711dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* stop the process so we can debug */ 712dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project kill(cr.pid, SIGSTOP); 713dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 71409e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng /* 71509e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng * If a thread has been attached by ptrace, make sure it is detached 716dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * successfully otherwise we will get a zombie. 71709e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng */ 718dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (tid_attach_status == 0) { 719dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int detach_status; 720dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* detach so we can attach gdbserver */ 721dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project detach_status = ptrace(PTRACE_DETACH, tid, 0, 0); 722dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project need_cleanup |= (detach_status != 0); 723dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 724dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 725dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* 726dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * if debug.db.uid is set, its value indicates if we should wait 727dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * for user action for the crashing process. 728dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * in this case, we log a message and turn the debug LED on 729dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * waiting for a gdb connection (for instance) 730dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 731dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 732dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if ((signed)cr.uid <= debug_uid) { 733dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project wait_for_user_action(tid, &cr); 734dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 735dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 736e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden /* 737e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden * Resume stopped process (so it can crash in peace). If we didn't 738e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden * successfully detach, we're still the parent, and the actual parent 739e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden * won't receive a death notification via wait(2). At this point 740e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden * there's not much we can do about that. 741e5cc5396e83d12b7ca02ff6096a9950807aa010dAndy McFadden */ 742dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project kill(cr.pid, SIGCONT); 743dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 744dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (need_cleanup) { 745dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG("debuggerd committing suicide to free the zombie!\n"); 746dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project kill(getpid(), SIGKILL); 747dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 748dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 749dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fd != -1) close(fd); 750dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 751dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 752849249064cae9c1bb23b0204b5d35b832567801eBruce Beare 75309e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Chengint main() 754dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 755dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int s; 756dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct sigaction act; 757849249064cae9c1bb23b0204b5d35b832567801eBruce Beare int logsocket = -1; 75809e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng 75944e12eceecd0be8ba832a003733bfc859b2ccd9dAndy McFadden /* 76044e12eceecd0be8ba832a003733bfc859b2ccd9dAndy McFadden * debuggerd crashes can't be reported to debuggerd. Reset all of the 76144e12eceecd0be8ba832a003733bfc859b2ccd9dAndy McFadden * crash handlers. 76244e12eceecd0be8ba832a003733bfc859b2ccd9dAndy McFadden */ 76344e12eceecd0be8ba832a003733bfc859b2ccd9dAndy McFadden signal(SIGILL, SIG_DFL); 76444e12eceecd0be8ba832a003733bfc859b2ccd9dAndy McFadden signal(SIGABRT, SIG_DFL); 76544e12eceecd0be8ba832a003733bfc859b2ccd9dAndy McFadden signal(SIGBUS, SIG_DFL); 76644e12eceecd0be8ba832a003733bfc859b2ccd9dAndy McFadden signal(SIGFPE, SIG_DFL); 76744e12eceecd0be8ba832a003733bfc859b2ccd9dAndy McFadden signal(SIGSEGV, SIG_DFL); 76844e12eceecd0be8ba832a003733bfc859b2ccd9dAndy McFadden signal(SIGSTKFLT, SIG_DFL); 76944e12eceecd0be8ba832a003733bfc859b2ccd9dAndy McFadden signal(SIGPIPE, SIG_DFL); 77044e12eceecd0be8ba832a003733bfc859b2ccd9dAndy McFadden 77109e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng logsocket = socket_local_client("logd", 772dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_DGRAM); 773dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(logsocket < 0) { 774dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project logsocket = -1; 775dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 776dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fcntl(logsocket, F_SETFD, FD_CLOEXEC); 777dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 778dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 779dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project act.sa_handler = SIG_DFL; 780dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sigemptyset(&act.sa_mask); 781dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sigaddset(&act.sa_mask,SIGCHLD); 782dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project act.sa_flags = SA_NOCLDWAIT; 783dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sigaction(SIGCHLD, &act, 0); 78409e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng 78509e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng s = socket_local_server("android:debuggerd", 786dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM); 787dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(s < 0) return -1; 788dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fcntl(s, F_SETFD, FD_CLOEXEC); 789dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 790dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOG("debuggerd: " __DATE__ " " __TIME__ "\n"); 79109e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng 792dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for(;;) { 793dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct sockaddr addr; 794dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project socklen_t alen; 795dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int fd; 79609e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng 797dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project alen = sizeof(addr); 798655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden XLOG("waiting for connection\n"); 799dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd = accept(s, &addr, &alen); 800655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden if(fd < 0) { 801655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden XLOG("accept failed: %s\n", strerror(errno)); 802655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden continue; 803655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden } 80409e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng 805dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fcntl(fd, F_SETFD, FD_CLOEXEC); 806dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 807dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project handle_crashing_process(fd); 808dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 809dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 810dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 811