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 #define LOG_TAG "DEBUG" 18 19 #include "libdebuggerd/backtrace.h" 20 21 #include <dirent.h> 22 #include <errno.h> 23 #include <inttypes.h> 24 #include <limits.h> 25 #include <stddef.h> 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <sys/ptrace.h> 30 #include <sys/types.h> 31 #include <unistd.h> 32 33 #include <map> 34 #include <memory> 35 #include <string> 36 37 #include <android-base/strings.h> 38 #include <android-base/unique_fd.h> 39 #include <log/log.h> 40 #include <unwindstack/Unwinder.h> 41 42 #include "libdebuggerd/types.h" 43 #include "libdebuggerd/utility.h" 44 #include "util.h" 45 46 static void dump_process_header(log_t* log, pid_t pid, 47 const std::vector<std::string>& command_line) { 48 _LOG(log, logtype::BACKTRACE, "\n\n----- pid %d at %s -----\n", pid, get_timestamp().c_str()); 49 50 if (!command_line.empty()) { 51 _LOG(log, logtype::BACKTRACE, "Cmd line: %s\n", android::base::Join(command_line, " ").c_str()); 52 } 53 _LOG(log, logtype::BACKTRACE, "ABI: '%s'\n", ABI_STRING); 54 } 55 56 static void dump_process_footer(log_t* log, pid_t pid) { 57 _LOG(log, logtype::BACKTRACE, "\n----- end %d -----\n", pid); 58 } 59 60 void dump_backtrace_thread(int output_fd, unwindstack::Unwinder* unwinder, 61 const ThreadInfo& thread) { 62 log_t log; 63 log.tfd = output_fd; 64 log.amfd_data = nullptr; 65 66 _LOG(&log, logtype::BACKTRACE, "\n\"%s\" sysTid=%d\n", thread.thread_name.c_str(), thread.tid); 67 68 unwinder->SetRegs(thread.registers.get()); 69 unwinder->Unwind(); 70 if (unwinder->NumFrames() == 0) { 71 _LOG(&log, logtype::THREAD, "Unwind failed: tid = %d\n", thread.tid); 72 if (unwinder->LastErrorCode() != unwindstack::ERROR_NONE) { 73 _LOG(&log, logtype::THREAD, " Error code: %s\n", unwinder->LastErrorCodeString()); 74 _LOG(&log, logtype::THREAD, " Error address: 0x%" PRIx64 "\n", unwinder->LastErrorAddress()); 75 } 76 return; 77 } 78 79 log_backtrace(&log, unwinder, " "); 80 } 81 82 void dump_backtrace(android::base::unique_fd output_fd, unwindstack::Unwinder* unwinder, 83 const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread) { 84 log_t log; 85 log.tfd = output_fd.get(); 86 log.amfd_data = nullptr; 87 88 auto target = thread_info.find(target_thread); 89 if (target == thread_info.end()) { 90 ALOGE("failed to find target thread in thread info"); 91 return; 92 } 93 94 dump_process_header(&log, target->second.pid, target->second.command_line); 95 96 dump_backtrace_thread(output_fd.get(), unwinder, target->second); 97 for (const auto& [tid, info] : thread_info) { 98 if (tid != target_thread) { 99 dump_backtrace_thread(output_fd.get(), unwinder, info); 100 } 101 } 102 103 dump_process_footer(&log, target->second.pid); 104 } 105 106 void dump_backtrace_header(int output_fd) { 107 log_t log; 108 log.tfd = output_fd; 109 log.amfd_data = nullptr; 110 111 pid_t pid = getpid(); 112 dump_process_header(&log, pid, get_command_line(pid)); 113 } 114 115 void dump_backtrace_footer(int output_fd) { 116 log_t log; 117 log.tfd = output_fd; 118 log.amfd_data = nullptr; 119 120 dump_process_footer(&log, getpid()); 121 } 122