diff options
Diffstat (limited to 'debuggerd/libdebuggerd/backtrace.cpp')
-rw-r--r-- | debuggerd/libdebuggerd/backtrace.cpp | 81 |
1 files changed, 31 insertions, 50 deletions
diff --git a/debuggerd/libdebuggerd/backtrace.cpp b/debuggerd/libdebuggerd/backtrace.cpp index f616e1ba0..f0a01f41c 100644 --- a/debuggerd/libdebuggerd/backtrace.cpp +++ b/debuggerd/libdebuggerd/backtrace.cpp | |||
@@ -30,12 +30,15 @@ | |||
30 | #include <time.h> | 30 | #include <time.h> |
31 | #include <unistd.h> | 31 | #include <unistd.h> |
32 | 32 | ||
33 | #include <map> | ||
33 | #include <memory> | 34 | #include <memory> |
34 | #include <string> | 35 | #include <string> |
35 | 36 | ||
37 | #include <android-base/unique_fd.h> | ||
36 | #include <backtrace/Backtrace.h> | 38 | #include <backtrace/Backtrace.h> |
37 | #include <log/log.h> | 39 | #include <log/log.h> |
38 | 40 | ||
41 | #include "libdebuggerd/types.h" | ||
39 | #include "libdebuggerd/utility.h" | 42 | #include "libdebuggerd/utility.h" |
40 | 43 | ||
41 | static void dump_process_header(log_t* log, pid_t pid, const char* process_name) { | 44 | static void dump_process_header(log_t* log, pid_t pid, const char* process_name) { |
@@ -56,62 +59,46 @@ static void dump_process_footer(log_t* log, pid_t pid) { | |||
56 | _LOG(log, logtype::BACKTRACE, "\n----- end %d -----\n", pid); | 59 | _LOG(log, logtype::BACKTRACE, "\n----- end %d -----\n", pid); |
57 | } | 60 | } |
58 | 61 | ||
59 | static void log_thread_name(log_t* log, pid_t tid, const char* thread_name) { | 62 | void dump_backtrace_thread(int output_fd, BacktraceMap* map, const ThreadInfo& thread) { |
60 | _LOG(log, logtype::BACKTRACE, "\n\"%s\" sysTid=%d\n", thread_name, tid); | ||
61 | } | ||
62 | |||
63 | static void dump_thread(log_t* log, BacktraceMap* map, pid_t pid, pid_t tid, | ||
64 | const std::string& thread_name) { | ||
65 | log_thread_name(log, tid, thread_name.c_str()); | ||
66 | |||
67 | std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid, map)); | ||
68 | if (backtrace->Unwind(0)) { | ||
69 | dump_backtrace_to_log(backtrace.get(), log, " "); | ||
70 | } else { | ||
71 | ALOGE("Unwind failed: tid = %d: %s", tid, | ||
72 | backtrace->GetErrorString(backtrace->GetError()).c_str()); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | void dump_backtrace(int fd, BacktraceMap* map, pid_t pid, pid_t tid, const std::string& process_name, | ||
77 | const std::map<pid_t, std::string>& threads, std::string* amfd_data) { | ||
78 | log_t log; | 63 | log_t log; |
79 | log.tfd = fd; | 64 | log.tfd = output_fd; |
80 | log.amfd_data = amfd_data; | 65 | log.amfd_data = nullptr; |
81 | 66 | ||
82 | dump_process_header(&log, pid, process_name.c_str()); | 67 | _LOG(&log, logtype::BACKTRACE, "\n\"%s\" sysTid=%d\n", thread.thread_name.c_str(), thread.tid); |
83 | dump_thread(&log, map, pid, tid, threads.find(tid)->second.c_str()); | ||
84 | 68 | ||
85 | for (const auto& it : threads) { | 69 | std::vector<backtrace_frame_data_t> frames; |
86 | pid_t thread_tid = it.first; | 70 | if (!Backtrace::Unwind(thread.registers.get(), map, &frames, 0, nullptr)) { |
87 | const std::string& thread_name = it.second; | 71 | _LOG(&log, logtype::THREAD, "Unwind failed: tid = %d", thread.tid); |
88 | if (thread_tid != tid) { | 72 | return; |
89 | dump_thread(&log, map, pid, thread_tid, thread_name.c_str()); | ||
90 | } | ||
91 | } | 73 | } |
92 | 74 | ||
93 | dump_process_footer(&log, pid); | 75 | for (auto& frame : frames) { |
76 | _LOG(&log, logtype::BACKTRACE, " %s\n", Backtrace::FormatFrameData(&frame).c_str()); | ||
77 | } | ||
94 | } | 78 | } |
95 | 79 | ||
96 | void dump_backtrace_ucontext(int output_fd, ucontext_t* ucontext) { | 80 | void dump_backtrace(android::base::unique_fd output_fd, BacktraceMap* map, |
97 | pid_t pid = getpid(); | 81 | const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread) { |
98 | pid_t tid = gettid(); | ||
99 | |||
100 | log_t log; | 82 | log_t log; |
101 | log.tfd = output_fd; | 83 | log.tfd = output_fd.get(); |
102 | log.amfd_data = nullptr; | 84 | log.amfd_data = nullptr; |
103 | 85 | ||
104 | char thread_name[16]; | 86 | auto target = thread_info.find(target_thread); |
105 | read_with_default("/proc/self/comm", thread_name, sizeof(thread_name), "<unknown>"); | 87 | if (target == thread_info.end()) { |
106 | log_thread_name(&log, tid, thread_name); | 88 | ALOGE("failed to find target thread in thread info"); |
89 | return; | ||
90 | } | ||
107 | 91 | ||
108 | std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid)); | 92 | dump_process_header(&log, target->second.pid, target->second.process_name.c_str()); |
109 | if (backtrace->Unwind(0, ucontext)) { | 93 | |
110 | dump_backtrace_to_log(backtrace.get(), &log, " "); | 94 | dump_backtrace_thread(output_fd.get(), map, target->second); |
111 | } else { | 95 | for (const auto& [tid, info] : thread_info) { |
112 | ALOGE("Unwind failed: tid = %d: %s", tid, | 96 | if (tid != target_thread) { |
113 | backtrace->GetErrorString(backtrace->GetError()).c_str()); | 97 | dump_backtrace_thread(output_fd.get(), map, info); |
98 | } | ||
114 | } | 99 | } |
100 | |||
101 | dump_process_footer(&log, target->second.pid); | ||
115 | } | 102 | } |
116 | 103 | ||
117 | void dump_backtrace_header(int output_fd) { | 104 | void dump_backtrace_header(int output_fd) { |
@@ -131,9 +118,3 @@ void dump_backtrace_footer(int output_fd) { | |||
131 | 118 | ||
132 | dump_process_footer(&log, getpid()); | 119 | dump_process_footer(&log, getpid()); |
133 | } | 120 | } |
134 | |||
135 | void dump_backtrace_to_log(Backtrace* backtrace, log_t* log, const char* prefix) { | ||
136 | for (size_t i = 0; i < backtrace->NumFrames(); i++) { | ||
137 | _LOG(log, logtype::BACKTRACE, "%s%s\n", prefix, backtrace->FormatFrameData(i).c_str()); | ||
138 | } | ||
139 | } | ||