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