backtrace.c revision 9cec175c66100d9edbb1054f3f2977a5c3f80af2
1053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown/* 2053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * Copyright (C) 2012 The Android Open Source Project 3053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * 4053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 5053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * you may not use this file except in compliance with the License. 6053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * You may obtain a copy of the License at 7053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * 8053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 9053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * 10053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * Unless required by applicable law or agreed to in writing, software 11053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 12053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * See the License for the specific language governing permissions and 14053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * limitations under the License. 15053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown */ 16053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 17053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <stddef.h> 18053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <stdbool.h> 19053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <stdlib.h> 20053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <string.h> 21053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <stdio.h> 22053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <time.h> 23053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <errno.h> 24053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <limits.h> 25053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <dirent.h> 26053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <unistd.h> 27053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <sys/types.h> 28053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <sys/ptrace.h> 29053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 30053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <corkscrew/backtrace.h> 31053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 32053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include "tombstone.h" 33053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include "utility.h" 34053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 35053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#define STACK_DEPTH 32 36053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 37053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic void dump_process_header(log_t* log, pid_t pid) { 38053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown char path[PATH_MAX]; 39053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown char procnamebuf[1024]; 40053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown char* procname = NULL; 41053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown FILE* fp; 42053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 43053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown snprintf(path, sizeof(path), "/proc/%d/cmdline", pid); 44053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if ((fp = fopen(path, "r"))) { 45053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown procname = fgets(procnamebuf, sizeof(procnamebuf), fp); 46053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown fclose(fp); 47053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 48053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 49053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown time_t t = time(NULL); 50053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown struct tm tm; 51053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown localtime_r(&t, &tm); 52053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown char timestr[64]; 53053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown strftime(timestr, sizeof(timestr), "%F %T", &tm); 54053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown _LOG(log, false, "\n\n----- pid %d at %s -----\n", pid, timestr); 55053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 56053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (procname) { 579cec175c66100d9edbb1054f3f2977a5c3f80af2Jeff Brown _LOG(log, false, "Cmd line: %s\n", procname); 58053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 59053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown} 60053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 61053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic void dump_process_footer(log_t* log, pid_t pid) { 62053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown _LOG(log, false, "\n----- end %d -----\n", pid); 63053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown} 64053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 65053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic void dump_thread(log_t* log, pid_t tid, ptrace_context_t* context, bool attached, 66053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown bool* detach_failed, int* total_sleep_time_usec) { 67053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown char path[PATH_MAX]; 68053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown char threadnamebuf[1024]; 69053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown char* threadname = NULL; 70053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown FILE* fp; 71053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 72053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown snprintf(path, sizeof(path), "/proc/%d/comm", tid); 73053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if ((fp = fopen(path, "r"))) { 74053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown threadname = fgets(threadnamebuf, sizeof(threadnamebuf), fp); 75053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown fclose(fp); 76053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (threadname) { 77053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown size_t len = strlen(threadname); 78053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (len && threadname[len - 1] == '\n') { 79053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown threadname[len - 1] = '\0'; 80053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 81053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 82053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 83053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 84053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown _LOG(log, false, "\n\"%s\" sysTid=%d\n", threadname ? threadname : "<unknown>", tid); 85053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 86053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (!attached && ptrace(PTRACE_ATTACH, tid, 0, 0) < 0) { 87053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown _LOG(log, false, "Could not attach to thread: %s\n", strerror(errno)); 88053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown return; 89053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 90053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 91053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown wait_for_stop(tid, total_sleep_time_usec); 92053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 93053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown backtrace_frame_t backtrace[STACK_DEPTH]; 94053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown ssize_t frames = unwind_backtrace_ptrace(tid, context, backtrace, 0, STACK_DEPTH); 95053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (frames <= 0) { 96053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown _LOG(log, false, "Could not obtain stack trace for thread.\n"); 97053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } else { 98053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown backtrace_symbol_t backtrace_symbols[STACK_DEPTH]; 99053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown get_backtrace_symbols_ptrace(context, backtrace, frames, backtrace_symbols); 100053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown for (size_t i = 0; i < (size_t)frames; i++) { 101053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown char line[MAX_BACKTRACE_LINE_LENGTH]; 102053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown format_backtrace_line(i, &backtrace[i], &backtrace_symbols[i], 103053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown line, MAX_BACKTRACE_LINE_LENGTH); 104053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown _LOG(log, false, " %s\n", line); 105053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 106053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown free_backtrace_symbols(backtrace_symbols, frames); 107053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 108053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 109053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (!attached && ptrace(PTRACE_DETACH, tid, 0, 0) != 0) { 110053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown LOG("ptrace detach from %d failed: %s\n", tid, strerror(errno)); 111053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown *detach_failed = true; 112053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 113053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown} 114053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 115053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownvoid dump_backtrace(int fd, pid_t pid, pid_t tid, bool* detach_failed, 116053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown int* total_sleep_time_usec) { 117053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown log_t log; 118053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown log.tfd = fd; 119053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown log.quiet = true; 120053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 121053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown ptrace_context_t* context = load_ptrace_context(tid); 122053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown dump_process_header(&log, pid); 123053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown dump_thread(&log, tid, context, true, detach_failed, total_sleep_time_usec); 124053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 125053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown char task_path[64]; 126053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid); 127053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown DIR* d = opendir(task_path); 128053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (d) { 129053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown struct dirent debuf; 130053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown struct dirent *de; 131053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown while (!readdir_r(d, &debuf, &de) && de) { 132053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) { 133053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown continue; 134053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 135053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 136053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown char* end; 137053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown pid_t new_tid = strtoul(de->d_name, &end, 10); 138053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (*end || new_tid == tid) { 139053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown continue; 140053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 141053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 142053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown dump_thread(&log, new_tid, context, false, detach_failed, total_sleep_time_usec); 143053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 144053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown closedir(d); 145053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 146053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 147053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown dump_process_footer(&log, pid); 148053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown free_ptrace_context(context); 149053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown} 150