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 } 526053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown return do_explicit_dump(tid, dump_backtrace); 5279524e4158fbb988b6a5e4f5be68ee10b7e4dd6d8Jeff Brown} 528