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>
26053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <time.h>
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/ptrace.h>
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/wait.h>
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/exec_elf.h>
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/stat.h>
329524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown#include <sys/poll.h>
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/sockets.h>
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/logd.h>
3641e0cef301637cd1f2daf72953d1230b7fb174b8Andy McFadden#include <cutils/logger.h>
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/properties.h>
38053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <cutils/debugger.h>
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
4013e715b491e876865e752a3a69dd6f347049a488Jeff Brown#include <corkscrew/backtrace.h>
4113e715b491e876865e752a3a69dd6f347049a488Jeff Brown
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/input.h>
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <private/android_filesystem_config.h>
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
46053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include "backtrace.h"
4713e715b491e876865e752a3a69dd6f347049a488Jeff Brown#include "getevent.h"
48053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include "tombstone.h"
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "utility.h"
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
51053b865412d1982ad1dc0e840898d82527deeb99Jeff Browntypedef struct {
52053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    debugger_action_t action;
53053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    pid_t pid, tid;
54053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    uid_t uid, gid;
55053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown} debugger_request_t;
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectwrite_string(const char* file, const char* string)
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int len;
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fd;
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ssize_t amt;
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd = open(file, O_RDWR);
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    len = strlen(string);
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (fd < 0)
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -errno;
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    amt = write(fd, string, len);
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    close(fd);
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return amt >= 0 ? 0 : -errno;
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid init_debug_led(void)
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // trout leds
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    write_string("/sys/class/leds/red/brightness", "0");
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    write_string("/sys/class/leds/green/brightness", "0");
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    write_string("/sys/class/leds/blue/brightness", "0");
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    write_string("/sys/class/leds/red/device/blink", "0");
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // sardine leds
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    write_string("/sys/class/leds/left/cadence", "0,0");
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid enable_debug_led(void)
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // trout leds
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    write_string("/sys/class/leds/red/brightness", "255");
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // sardine leds
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    write_string("/sys/class/leds/left/cadence", "1,0");
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid disable_debug_led(void)
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // trout leds
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    write_string("/sys/class/leds/red/brightness", "0");
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // sardine leds
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    write_string("/sys/class/leds/left/cadence", "0,0");
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1029524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brownstatic void wait_for_user_action(pid_t pid) {
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* First log a helpful message */
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    LOG(    "********************************************************\n"
1053bfdcc979da0f857b014318f3df5d95a0f93eb27Andy McFadden            "* Process %d has been suspended while crashing.  To\n"
1069524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            "* attach gdbserver for a gdb connection on port 5039\n"
1079524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            "* and start gdbclient:\n"
1083bfdcc979da0f857b014318f3df5d95a0f93eb27Andy McFadden            "*\n"
1099524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            "*     gdbclient app_process :5039 %d\n"
1103bfdcc979da0f857b014318f3df5d95a0f93eb27Andy McFadden            "*\n"
1119524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            "* Wait for gdb to start, then press HOME or VOLUME DOWN key\n"
1129524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            "* to let the process continue crashing.\n"
11309e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng            "********************************************************\n",
1149524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            pid, pid);
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1169524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    /* wait for HOME or VOLUME DOWN key */
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (init_getevent() == 0) {
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int ms = 1200 / 10;
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int dit = 1;
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int dah = 3*dit;
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int _       = -dit;
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int ___     = 3*_;
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int _______ = 7*_;
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const signed char codes[] = {
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           dit,_,dit,_,dit,___,dah,_,dah,_,dah,___,dit,_,dit,_,dit,_______
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        };
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        size_t s = 0;
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        struct input_event e;
1299524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        bool done = false;
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        init_debug_led();
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        enable_debug_led();
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        do {
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int timeout = abs((int)(codes[s])) * ms;
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int res = get_event(&e, timeout);
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (res == 0) {
1369524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                if (e.type == EV_KEY
1379524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                        && (e.code == KEY_HOME || e.code == KEY_VOLUMEDOWN)
1389524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                        && e.value == 0) {
1399524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                    done = true;
1409524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                }
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else if (res == 1) {
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (++s >= sizeof(codes)/sizeof(*codes))
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    s = 0;
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (codes[s] > 0) {
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    enable_debug_led();
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                } else {
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    disable_debug_led();
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
1509524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        } while (!done);
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        uninit_getevent();
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* don't forget to turn debug led off */
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    disable_debug_led();
1569524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    LOG("debuggerd resuming process %d", pid);
1579524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown}
15809e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng
1599524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brownstatic int get_process_info(pid_t tid, pid_t* out_pid, uid_t* out_uid, uid_t* out_gid) {
1609524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    char path[64];
1619524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    snprintf(path, sizeof(path), "/proc/%d/status", tid);
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1639524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    FILE* fp = fopen(path, "r");
1649524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    if (!fp) {
1659524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        return -1;
1669524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    }
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1689524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    int fields = 0;
1699524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    char line[1024];
1709524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    while (fgets(line, sizeof(line), fp)) {
1719524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        size_t len = strlen(line);
1729524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        if (len > 6 && !memcmp(line, "Tgid:\t", 6)) {
1739524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            *out_pid = atoi(line + 6);
1749524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            fields |= 1;
1759524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        } else if (len > 5 && !memcmp(line, "Uid:\t", 5)) {
1769524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            *out_uid = atoi(line + 5);
1779524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            fields |= 2;
1789524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        } else if (len > 5 && !memcmp(line, "Gid:\t", 5)) {
1799524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            *out_gid = atoi(line + 5);
1809524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            fields |= 4;
1819524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        }
1829524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    }
1839524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    fclose(fp);
1849524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    return fields == 7 ? 0 : -1;
1859524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown}
18613e715b491e876865e752a3a69dd6f347049a488Jeff Brown
187053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic int read_request(int fd, debugger_request_t* out_request) {
1889524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    struct ucred cr;
1899524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    int len = sizeof(cr);
1909524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    int status = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &len);
1919524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    if (status != 0) {
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        LOG("cannot get credentials\n");
1939524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        return -1;
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
19609e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng    XLOG("reading tid\n");
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fcntl(fd, F_SETFL, O_NONBLOCK);
1989524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown
1999524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    struct pollfd pollfds[1];
2009524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    pollfds[0].fd = fd;
2019524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    pollfds[0].events = POLLIN;
2029524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    pollfds[0].revents = 0;
2039524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    status = TEMP_FAILURE_RETRY(poll(pollfds, 1, 3000));
2049524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    if (status != 1) {
2059524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        LOG("timed out reading tid\n");
2069524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        return -1;
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
209053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    debugger_msg_t msg;
210053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    status = TEMP_FAILURE_RETRY(read(fd, &msg, sizeof(msg)));
2119524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    if (status < 0) {
2129524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        LOG("read failure? %s\n", strerror(errno));
2139524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        return -1;
2149524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    }
215053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    if (status != sizeof(msg)) {
2169524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        LOG("invalid crash request of size %d\n", status);
2179524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        return -1;
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
21909e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng
220053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    out_request->action = msg.action;
221053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    out_request->tid = msg.tid;
222053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    out_request->pid = cr.pid;
223053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    out_request->uid = cr.uid;
224053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    out_request->gid = cr.gid;
225053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
226053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    if (msg.action == DEBUGGER_ACTION_CRASH) {
227053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        /* Ensure that the tid reported by the crashing process is valid. */
228053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        char buf[64];
229053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        struct stat s;
230053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        snprintf(buf, sizeof buf, "/proc/%d/task/%d", out_request->pid, out_request->tid);
231053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        if(stat(buf, &s)) {
232053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            LOG("tid %d does not exist in pid %d. ignoring debug request\n",
233053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                    out_request->tid, out_request->pid);
234053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            return -1;
235053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
236053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    } else if (cr.uid == 0
237053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            || (cr.uid == AID_SYSTEM && msg.action == DEBUGGER_ACTION_DUMP_BACKTRACE)) {
238053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        /* Only root or system can ask us to attach to any process and dump it explicitly.
239053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown         * However, system is only allowed to collect backtraces but cannot dump tombstones. */
2409524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        status = get_process_info(out_request->tid, &out_request->pid,
2419524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                &out_request->uid, &out_request->gid);
2429524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        if (status < 0) {
2439524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            LOG("tid %d does not exist. ignoring explicit dump request\n",
2449524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                    out_request->tid);
2459524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            return -1;
2469524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        }
247053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    } else {
248053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        /* No one else is not allowed to dump arbitrary processes. */
2499524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        return -1;
250655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden    }
2519524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    return 0;
2529524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown}
25302526d486803de153d03851f4d5f9be7c555e46cDavid 'Digit' Turner
254053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic bool should_attach_gdb(debugger_request_t* request) {
255053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    if (request->action == DEBUGGER_ACTION_CRASH) {
2569524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        char value[PROPERTY_VALUE_MAX];
2579524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        property_get("debug.db.uid", value, "-1");
2589524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        int debug_uid = atoi(value);
2599524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        return debug_uid >= 0 && request->uid <= (uid_t)debug_uid;
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
2619524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    return false;
2629524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown}
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2649524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brownstatic void handle_request(int fd) {
2659524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    XLOG("handle_request(%d)\n", fd);
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
267053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    debugger_request_t request;
2689524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    int status = read_request(fd, &request);
2699524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    if (!status) {
270424e07fcf655b65306bb846115e22594d6527056Andy McFadden        XLOG("BOOM: pid=%d uid=%d gid=%d tid=%d\n",
271424e07fcf655b65306bb846115e22594d6527056Andy McFadden            request.pid, request.uid, request.gid, request.tid);
272655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden
2739524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        /* At this point, the thread that made the request is blocked in
2749524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown         * a read() call.  If the thread has crashed, then this gives us
2759524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown         * time to PTRACE_ATTACH to it before it has a chance to really fault.
2769524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown         *
2779524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown         * The PTRACE_ATTACH sends a SIGSTOP to the target process, but it
2789524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown         * won't necessarily have stopped by the time ptrace() returns.  (We
2799524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown         * currently assume it does.)  We write to the file descriptor to
2809524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown         * ensure that it can run as soon as we call PTRACE_CONT below.
2819524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown         * See details in bionic/libc/linker/debugger.c, in function
2829524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown         * debugger_signal_handler().
2839524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown         */
2849524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        if (ptrace(PTRACE_ATTACH, request.tid, 0, 0)) {
2859524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            LOG("ptrace attach failed: %s\n", strerror(errno));
2869524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        } else {
2879524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            bool detach_failed = false;
2889524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            bool attach_gdb = should_attach_gdb(&request);
289053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            if (TEMP_FAILURE_RETRY(write(fd, "\0", 1)) != 1) {
2909524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                LOG("failed responding to client: %s\n", strerror(errno));
2919524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            } else {
292fb9804bfc2111aace2d56b15dbbe32e4d26767bcJeff Brown                char* tombstone_path = NULL;
293fb9804bfc2111aace2d56b15dbbe32e4d26767bcJeff Brown
294053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                if (request.action == DEBUGGER_ACTION_CRASH) {
295fb9804bfc2111aace2d56b15dbbe32e4d26767bcJeff Brown                    close(fd);
296fb9804bfc2111aace2d56b15dbbe32e4d26767bcJeff Brown                    fd = -1;
297fb9804bfc2111aace2d56b15dbbe32e4d26767bcJeff Brown                }
2989524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown
2999524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                int total_sleep_time_usec = 0;
3009524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                for (;;) {
3019524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                    int signal = wait_for_signal(request.tid, &total_sleep_time_usec);
3029524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                    if (signal < 0) {
3039524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                        break;
3049524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                    }
3059524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown
3069524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                    switch (signal) {
3079524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                    case SIGSTOP:
308053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                        if (request.action == DEBUGGER_ACTION_DUMP_TOMBSTONE) {
309053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                            XLOG("stopped -- dumping to tombstone\n");
310fb9804bfc2111aace2d56b15dbbe32e4d26767bcJeff Brown                            tombstone_path = engrave_tombstone(request.pid, request.tid,
311053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                                    signal, true, true, &detach_failed,
312053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                                    &total_sleep_time_usec);
313053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                        } else if (request.action == DEBUGGER_ACTION_DUMP_BACKTRACE) {
314053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                            XLOG("stopped -- dumping to fd\n");
315053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                            dump_backtrace(fd, request.pid, request.tid, &detach_failed,
316053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                                    &total_sleep_time_usec);
3179524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                        } else {
3189524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                            XLOG("stopped -- continuing\n");
3199524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                            status = ptrace(PTRACE_CONT, request.tid, 0, 0);
3209524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                            if (status) {
3219524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                                LOG("ptrace continue failed: %s\n", strerror(errno));
3229524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                            }
3239524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                            continue; /* loop again */
3249524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                        }
3259524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                        break;
3269524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown
3279524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                    case SIGILL:
3289524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                    case SIGABRT:
3299524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                    case SIGBUS:
3309524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                    case SIGFPE:
3319524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                    case SIGSEGV:
332424e07fcf655b65306bb846115e22594d6527056Andy McFadden                    case SIGPIPE:
333231e3c83a3a70b11160fb0da108ebf2e0e7470e2Chris Dearman#ifdef SIGSTKFLT
334231e3c83a3a70b11160fb0da108ebf2e0e7470e2Chris Dearman                    case SIGSTKFLT:
335231e3c83a3a70b11160fb0da108ebf2e0e7470e2Chris Dearman#endif
336231e3c83a3a70b11160fb0da108ebf2e0e7470e2Chris Dearman                        {
3379524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                        XLOG("stopped -- fatal signal\n");
338424e07fcf655b65306bb846115e22594d6527056Andy McFadden                        /*
339424e07fcf655b65306bb846115e22594d6527056Andy McFadden                         * Send a SIGSTOP to the process to make all of
340424e07fcf655b65306bb846115e22594d6527056Andy McFadden                         * the non-signaled threads stop moving.  Without
341424e07fcf655b65306bb846115e22594d6527056Andy McFadden                         * this we get a lot of "ptrace detach failed:
342424e07fcf655b65306bb846115e22594d6527056Andy McFadden                         * No such process".
343424e07fcf655b65306bb846115e22594d6527056Andy McFadden                         */
344424e07fcf655b65306bb846115e22594d6527056Andy McFadden                        kill(request.pid, SIGSTOP);
3459524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                        /* don't dump sibling threads when attaching to GDB because it
3469524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                         * makes the process less reliable, apparently... */
347fb9804bfc2111aace2d56b15dbbe32e4d26767bcJeff Brown                        tombstone_path = engrave_tombstone(request.pid, request.tid,
348053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                                signal, !attach_gdb, false, &detach_failed,
349053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                                &total_sleep_time_usec);
3509524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                        break;
3519524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                    }
3529524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown
3539524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                    default:
3549524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                        XLOG("stopped -- unexpected signal\n");
3559524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                        LOG("process stopped due to unexpected signal %d\n", signal);
3569524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                        break;
3579524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                    }
3589524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                    break;
3599524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                }
360fb9804bfc2111aace2d56b15dbbe32e4d26767bcJeff Brown
361053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown                if (request.action == DEBUGGER_ACTION_DUMP_TOMBSTONE) {
362fb9804bfc2111aace2d56b15dbbe32e4d26767bcJeff Brown                    if (tombstone_path) {
363fb9804bfc2111aace2d56b15dbbe32e4d26767bcJeff Brown                        write(fd, tombstone_path, strlen(tombstone_path));
364fb9804bfc2111aace2d56b15dbbe32e4d26767bcJeff Brown                    }
365fb9804bfc2111aace2d56b15dbbe32e4d26767bcJeff Brown                    close(fd);
366fb9804bfc2111aace2d56b15dbbe32e4d26767bcJeff Brown                    fd = -1;
367fb9804bfc2111aace2d56b15dbbe32e4d26767bcJeff Brown                }
368fb9804bfc2111aace2d56b15dbbe32e4d26767bcJeff Brown                free(tombstone_path);
3699524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            }
37009e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng
3719524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            XLOG("detaching\n");
3729524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            if (attach_gdb) {
3739524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                /* stop the process so we can debug */
3749524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                kill(request.pid, SIGSTOP);
375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3769524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                /* detach so we can attach gdbserver */
3779524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                if (ptrace(PTRACE_DETACH, request.tid, 0, 0)) {
3789524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                    LOG("ptrace detach from %d failed: %s\n", request.tid, strerror(errno));
3799524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                    detach_failed = true;
380dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
38109e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng
3829524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                /*
3839524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                 * if debug.db.uid is set, its value indicates if we should wait
3849524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                 * for user action for the crashing process.
3859524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                 * in this case, we log a message and turn the debug LED on
3869524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                 * waiting for a gdb connection (for instance)
3879524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                 */
3889524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                wait_for_user_action(request.pid);
3899524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            } else {
3909524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                /* just detach */
3919524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                if (ptrace(PTRACE_DETACH, request.tid, 0, 0)) {
3929524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                    LOG("ptrace detach from %d failed: %s\n", request.tid, strerror(errno));
3939524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                    detach_failed = true;
3949524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                }
395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
396dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3979524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            /* resume stopped process (so it can crash in peace). */
3989524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            kill(request.pid, SIGCONT);
3999524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown
4009524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            /* If we didn't successfully detach, we're still the parent, and the
4019524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown             * actual parent won't receive a death notification via wait(2).  At this point
4029524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown             * there's not much we can do about that. */
4039524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            if (detach_failed) {
4049524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                LOG("debuggerd committing suicide to free the zombie!\n");
4059524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown                kill(getpid(), SIGKILL);
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
40809e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng
409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
4109524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    if (fd >= 0) {
4119524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        close(fd);
412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
413dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
4159524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brownstatic int do_server() {
416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int s;
417dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct sigaction act;
418849249064cae9c1bb23b0204b5d35b832567801eBruce Beare    int logsocket = -1;
41909e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng
42044e12eceecd0be8ba832a003733bfc859b2ccd9dAndy McFadden    /*
42144e12eceecd0be8ba832a003733bfc859b2ccd9dAndy McFadden     * debuggerd crashes can't be reported to debuggerd.  Reset all of the
42244e12eceecd0be8ba832a003733bfc859b2ccd9dAndy McFadden     * crash handlers.
42344e12eceecd0be8ba832a003733bfc859b2ccd9dAndy McFadden     */
42444e12eceecd0be8ba832a003733bfc859b2ccd9dAndy McFadden    signal(SIGILL, SIG_DFL);
42544e12eceecd0be8ba832a003733bfc859b2ccd9dAndy McFadden    signal(SIGABRT, SIG_DFL);
42644e12eceecd0be8ba832a003733bfc859b2ccd9dAndy McFadden    signal(SIGBUS, SIG_DFL);
42744e12eceecd0be8ba832a003733bfc859b2ccd9dAndy McFadden    signal(SIGFPE, SIG_DFL);
42844e12eceecd0be8ba832a003733bfc859b2ccd9dAndy McFadden    signal(SIGSEGV, SIG_DFL);
42944e12eceecd0be8ba832a003733bfc859b2ccd9dAndy McFadden    signal(SIGPIPE, SIG_DFL);
430231e3c83a3a70b11160fb0da108ebf2e0e7470e2Chris Dearman#ifdef SIGSTKFLT
431424e07fcf655b65306bb846115e22594d6527056Andy McFadden    signal(SIGSTKFLT, SIG_DFL);
432231e3c83a3a70b11160fb0da108ebf2e0e7470e2Chris Dearman#endif
43344e12eceecd0be8ba832a003733bfc859b2ccd9dAndy McFadden
43409e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng    logsocket = socket_local_client("logd",
435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_DGRAM);
436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(logsocket < 0) {
437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        logsocket = -1;
438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
439dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fcntl(logsocket, F_SETFD, FD_CLOEXEC);
440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    act.sa_handler = SIG_DFL;
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sigemptyset(&act.sa_mask);
444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sigaddset(&act.sa_mask,SIGCHLD);
445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    act.sa_flags = SA_NOCLDWAIT;
446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sigaction(SIGCHLD, &act, 0);
44709e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng
448053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    s = socket_local_server(DEBUGGER_SOCKET_NAME,
449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
4509524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    if(s < 0) return 1;
451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fcntl(s, F_SETFD, FD_CLOEXEC);
452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    LOG("debuggerd: " __DATE__ " " __TIME__ "\n");
45409e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng
455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(;;) {
456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        struct sockaddr addr;
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        socklen_t alen;
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int fd;
45909e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng
460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        alen = sizeof(addr);
461655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden        XLOG("waiting for connection\n");
462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fd = accept(s, &addr, &alen);
463655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden        if(fd < 0) {
464655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden            XLOG("accept failed: %s\n", strerror(errno));
465655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden            continue;
466655835be2a0e6d656040f4dd8f7e3e1035734ef7Andy McFadden        }
46709e713789e31f640a80af1cddb2fc40cbeb02ad5Ben Cheng
468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fcntl(fd, F_SETFD, FD_CLOEXEC);
469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
4709524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        handle_request(fd);
4719524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    }
4729524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    return 0;
4739524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown}
4749524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown
475053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic int do_explicit_dump(pid_t tid, bool dump_backtrace) {
4769524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    fprintf(stdout, "Sending request to dump task %d.\n", tid);
4779524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown
478053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    if (dump_backtrace) {
479053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        fflush(stdout);
480053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        if (dump_backtrace_to_file(tid, fileno(stdout)) < 0) {
481053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            fputs("Error dumping backtrace.\n", stderr);
482053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            return 1;
483053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        }
484fb9804bfc2111aace2d56b15dbbe32e4d26767bcJeff Brown    } else {
485fb9804bfc2111aace2d56b15dbbe32e4d26767bcJeff Brown        char tombstone_path[PATH_MAX];
486053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        if (dump_tombstone(tid, tombstone_path, sizeof(tombstone_path)) < 0) {
487053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            fputs("Error dumping tombstone.\n", stderr);
488053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            return 1;
489fb9804bfc2111aace2d56b15dbbe32e4d26767bcJeff Brown        }
490053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        fprintf(stderr, "Tombstone written to: %s\n", tombstone_path);
491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
4949524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown
495053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic void usage() {
496053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    fputs("Usage: -b [<tid>]\n"
497053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            "  -b dump backtrace to console, otherwise dump full tombstone file\n"
498053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            "\n"
499053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            "If tid specified, sends a request to debuggerd to dump that task.\n"
500053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            "Otherwise, starts the debuggerd server.\n", stderr);
501053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown}
502053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
5039524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brownint main(int argc, char** argv) {
504053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    if (argc == 1) {
505053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        return do_server();
506053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
507053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown
508053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    bool dump_backtrace = false;
509053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    bool have_tid = false;
510053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    pid_t tid = 0;
511053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    for (int i = 1; i < argc; i++) {
512053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        if (!strcmp(argv[i], "-b")) {
513053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            dump_backtrace = true;
514053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        } else if (!have_tid) {
515053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            tid = atoi(argv[i]);
516053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            have_tid = true;
517053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        } else {
518053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown            usage();
5199524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown            return 1;
5209524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown        }
5219524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown    }
522053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    if (!have_tid) {
523053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        usage();
524053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown        return 1;
525053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown    }
526