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 17eb19e766322fb57ccde989e0e35b0ac3e28a4ac2Christopher Ferris#define LOG_TAG "DEBUG" 18eb19e766322fb57ccde989e0e35b0ac3e28a4ac2Christopher Ferris 19053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <stddef.h> 20053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <stdlib.h> 21053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <string.h> 22053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <stdio.h> 23053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <time.h> 24053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <errno.h> 25053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <limits.h> 26053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <dirent.h> 27053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <unistd.h> 28053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <sys/types.h> 29053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <sys/ptrace.h> 30053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 31f0861f9f8fb1884e863fdf5e1b95d69d43d8b1ffChristopher Ferris#include <memory> 32f0861f9f8fb1884e863fdf5e1b95d69d43d8b1ffChristopher Ferris 3320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris#include <backtrace/Backtrace.h> 34eb19e766322fb57ccde989e0e35b0ac3e28a4ac2Christopher Ferris 35eb19e766322fb57ccde989e0e35b0ac3e28a4ac2Christopher Ferris#include <log/log.h> 36053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 37365e4ae74568274ffd692c12fd7285a230d49a67Christopher Ferris#include "backtrace.h" 3862ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith 39053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include "utility.h" 40053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 41053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic void dump_process_header(log_t* log, pid_t pid) { 4220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris char path[PATH_MAX]; 4320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris char procnamebuf[1024]; 4420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris char* procname = NULL; 4520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris FILE* fp; 4620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris 4720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris snprintf(path, sizeof(path), "/proc/%d/cmdline", pid); 4820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris if ((fp = fopen(path, "r"))) { 4920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris procname = fgets(procnamebuf, sizeof(procnamebuf), fp); 5020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris fclose(fp); 5120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris } 5220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris 5320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris time_t t = time(NULL); 5420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris struct tm tm; 5520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris localtime_r(&t, &tm); 5620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris char timestr[64]; 5720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris strftime(timestr, sizeof(timestr), "%F %T", &tm); 589b12d53b1a180bb7c6c946649254e6f23e6ca04dJeff Brown _LOG(log, logtype::BACKTRACE, "\n\n----- pid %d at %s -----\n", pid, timestr); 5920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris 6020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris if (procname) { 6162ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith _LOG(log, logtype::BACKTRACE, "Cmd line: %s\n", procname); 6220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris } 639b12d53b1a180bb7c6c946649254e6f23e6ca04dJeff Brown _LOG(log, logtype::BACKTRACE, "ABI: '%s'\n", ABI_STRING); 64053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown} 65053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 66053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic void dump_process_footer(log_t* log, pid_t pid) { 6762ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith _LOG(log, logtype::BACKTRACE, "\n----- end %d -----\n", pid); 68053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown} 69053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 7020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferrisstatic void dump_thread( 7120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris log_t* log, pid_t tid, bool attached, bool* detach_failed, int* total_sleep_time_usec) { 7220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris char path[PATH_MAX]; 7320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris char threadnamebuf[1024]; 7420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris char* threadname = NULL; 7520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris FILE* fp; 7620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris 7720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris snprintf(path, sizeof(path), "/proc/%d/comm", tid); 7820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris if ((fp = fopen(path, "r"))) { 7920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris threadname = fgets(threadnamebuf, sizeof(threadnamebuf), fp); 8020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris fclose(fp); 8120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris if (threadname) { 8220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris size_t len = strlen(threadname); 8320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris if (len && threadname[len - 1] == '\n') { 8420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris threadname[len - 1] = '\0'; 8520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris } 86053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 8720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris } 88053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 8962ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith _LOG(log, logtype::BACKTRACE, "\n\"%s\" sysTid=%d\n", threadname ? threadname : "<unknown>", tid); 90053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 9120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris if (!attached && ptrace(PTRACE_ATTACH, tid, 0, 0) < 0) { 9262ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith _LOG(log, logtype::BACKTRACE, "Could not attach to thread: %s\n", strerror(errno)); 9320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris return; 9420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris } 95053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 9684ddb34a3af77dbe490aaa07b738bbfd7109d5baChristopher Ferris if (!attached && wait_for_sigstop(tid, total_sleep_time_usec, detach_failed) == -1) { 9784ddb34a3af77dbe490aaa07b738bbfd7109d5baChristopher Ferris return; 9884ddb34a3af77dbe490aaa07b738bbfd7109d5baChristopher Ferris } 99053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 100f0861f9f8fb1884e863fdf5e1b95d69d43d8b1ffChristopher Ferris std::unique_ptr<Backtrace> backtrace(Backtrace::Create(tid, BACKTRACE_CURRENT_THREAD)); 10120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris if (backtrace->Unwind(0)) { 10262ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith dump_backtrace_to_log(backtrace.get(), log, " "); 103eb19e766322fb57ccde989e0e35b0ac3e28a4ac2Christopher Ferris } else { 104eb19e766322fb57ccde989e0e35b0ac3e28a4ac2Christopher Ferris ALOGE("Unwind failed: tid = %d", tid); 10520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris } 106053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 10720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris if (!attached && ptrace(PTRACE_DETACH, tid, 0, 0) != 0) { 10850eb546ec1584c04cf18f1941a042d7c5d045a67Brigid Smith _LOG(log, logtype::ERROR, "ptrace detach from %d failed: %s\n", tid, strerror(errno)); 10920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris *detach_failed = true; 11020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris } 111053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown} 112053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 113ded2e5acfcf0c705f08577d0ccb720bd5037f4baChristopher Tatevoid dump_backtrace(int fd, int amfd, pid_t pid, pid_t tid, bool* detach_failed, 11420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris int* total_sleep_time_usec) { 11520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris log_t log; 11620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris log.tfd = fd; 11720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris log.amfd = amfd; 11820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris 11920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris dump_process_header(&log, pid); 12020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris dump_thread(&log, tid, true, detach_failed, total_sleep_time_usec); 12120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris 12220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris char task_path[64]; 12320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid); 12420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris DIR* d = opendir(task_path); 12520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris if (d != NULL) { 12620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris struct dirent* de = NULL; 12720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris while ((de = readdir(d)) != NULL) { 12820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) { 12920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris continue; 13020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris } 13120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris 13220303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris char* end; 13320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris pid_t new_tid = strtoul(de->d_name, &end, 10); 13420303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris if (*end || new_tid == tid) { 13520303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris continue; 13620303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris } 13720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris 13820303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris dump_thread(&log, new_tid, false, detach_failed, total_sleep_time_usec); 139053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 14020303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris closedir(d); 14120303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris } 142053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 14320303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris dump_process_footer(&log, pid); 144365e4ae74568274ffd692c12fd7285a230d49a67Christopher Ferris} 145365e4ae74568274ffd692c12fd7285a230d49a67Christopher Ferris 14662ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smithvoid dump_backtrace_to_log(Backtrace* backtrace, log_t* log, const char* prefix) { 14720303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris for (size_t i = 0; i < backtrace->NumFrames(); i++) { 14862ba489ba00a2689d4e257bc178cff87495f99d7Brigid Smith _LOG(log, logtype::BACKTRACE, "%s%s\n", prefix, backtrace->FormatFrameData(i).c_str()); 14920303f856f1f1cdb5af58af0b116b8c598f0ea5cChristopher Ferris } 150053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown} 151