1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <stddef.h> 18 #include <stdlib.h> 19 #include <string.h> 20 #include <stdio.h> 21 #include <time.h> 22 #include <errno.h> 23 #include <limits.h> 24 #include <dirent.h> 25 #include <unistd.h> 26 #include <sys/types.h> 27 #include <sys/ptrace.h> 28 29 #include <backtrace/Backtrace.h> 30 #include <UniquePtr.h> 31 32 #include "backtrace.h" 33 34 #include "utility.h" 35 36 static void dump_process_header(log_t* log, pid_t pid) { 37 char path[PATH_MAX]; 38 char procnamebuf[1024]; 39 char* procname = NULL; 40 FILE* fp; 41 42 snprintf(path, sizeof(path), "/proc/%d/cmdline", pid); 43 if ((fp = fopen(path, "r"))) { 44 procname = fgets(procnamebuf, sizeof(procnamebuf), fp); 45 fclose(fp); 46 } 47 48 time_t t = time(NULL); 49 struct tm tm; 50 localtime_r(&t, &tm); 51 char timestr[64]; 52 strftime(timestr, sizeof(timestr), "%F %T", &tm); 53 _LOG(log, logtype::BACKTRACE, "\n\n----- pid %d at %s -----\n", pid, timestr); 54 55 if (procname) { 56 _LOG(log, logtype::BACKTRACE, "Cmd line: %s\n", procname); 57 } 58 _LOG(log, logtype::BACKTRACE, "ABI: '%s'\n", ABI_STRING); 59 } 60 61 static void dump_process_footer(log_t* log, pid_t pid) { 62 _LOG(log, logtype::BACKTRACE, "\n----- end %d -----\n", pid); 63 } 64 65 static void dump_thread( 66 log_t* log, pid_t tid, bool attached, bool* detach_failed, int* total_sleep_time_usec) { 67 char path[PATH_MAX]; 68 char threadnamebuf[1024]; 69 char* threadname = NULL; 70 FILE* fp; 71 72 snprintf(path, sizeof(path), "/proc/%d/comm", tid); 73 if ((fp = fopen(path, "r"))) { 74 threadname = fgets(threadnamebuf, sizeof(threadnamebuf), fp); 75 fclose(fp); 76 if (threadname) { 77 size_t len = strlen(threadname); 78 if (len && threadname[len - 1] == '\n') { 79 threadname[len - 1] = '\0'; 80 } 81 } 82 } 83 84 _LOG(log, logtype::BACKTRACE, "\n\"%s\" sysTid=%d\n", threadname ? threadname : "<unknown>", tid); 85 86 if (!attached && ptrace(PTRACE_ATTACH, tid, 0, 0) < 0) { 87 _LOG(log, logtype::BACKTRACE, "Could not attach to thread: %s\n", strerror(errno)); 88 return; 89 } 90 91 wait_for_stop(tid, total_sleep_time_usec); 92 93 UniquePtr<Backtrace> backtrace(Backtrace::Create(tid, BACKTRACE_CURRENT_THREAD)); 94 if (backtrace->Unwind(0)) { 95 dump_backtrace_to_log(backtrace.get(), log, " "); 96 } 97 98 if (!attached && ptrace(PTRACE_DETACH, tid, 0, 0) != 0) { 99 _LOG(log, logtype::ERROR, "ptrace detach from %d failed: %s\n", tid, strerror(errno)); 100 *detach_failed = true; 101 } 102 } 103 104 void dump_backtrace(int fd, int amfd, pid_t pid, pid_t tid, bool* detach_failed, 105 int* total_sleep_time_usec) { 106 log_t log; 107 log.tfd = fd; 108 log.amfd = amfd; 109 110 dump_process_header(&log, pid); 111 dump_thread(&log, tid, true, detach_failed, total_sleep_time_usec); 112 113 char task_path[64]; 114 snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid); 115 DIR* d = opendir(task_path); 116 if (d != NULL) { 117 struct dirent* de = NULL; 118 while ((de = readdir(d)) != NULL) { 119 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) { 120 continue; 121 } 122 123 char* end; 124 pid_t new_tid = strtoul(de->d_name, &end, 10); 125 if (*end || new_tid == tid) { 126 continue; 127 } 128 129 dump_thread(&log, new_tid, false, detach_failed, total_sleep_time_usec); 130 } 131 closedir(d); 132 } 133 134 dump_process_footer(&log, pid); 135 } 136 137 void dump_backtrace_to_log(Backtrace* backtrace, log_t* log, const char* prefix) { 138 for (size_t i = 0; i < backtrace->NumFrames(); i++) { 139 _LOG(log, logtype::BACKTRACE, "%s%s\n", prefix, backtrace->FormatFrameData(i).c_str()); 140 } 141 } 142