Loading debuggerd/crash_dump.cpp +24 −5 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include <unistd.h> #include <limits> #include <map> #include <memory> #include <set> #include <vector> Loading @@ -36,6 +37,7 @@ #include <android-base/parseint.h> #include <android-base/properties.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/unique_fd.h> #include <cutils/sockets.h> #include <log/log.h> Loading @@ -52,7 +54,21 @@ #include "debuggerd/util.h" using android::base::unique_fd; using android::base::ReadFileToString; using android::base::StringPrintf; using android::base::Trim; static std::string get_process_name(pid_t pid) { std::string result = "<unknown>"; ReadFileToString(StringPrintf("/proc/%d/cmdline", pid), &result); return result; } static std::string get_thread_name(pid_t tid) { std::string result = "<unknown>"; ReadFileToString(StringPrintf("/proc/%d/comm", tid), &result); return Trim(result); } static bool pid_contains_tid(int pid_proc_fd, pid_t tid) { struct stat st; Loading Loading @@ -253,7 +269,7 @@ int main(int argc, char** argv) { } // Seize the siblings. std::set<pid_t> attached_siblings; std::map<pid_t, std::string> threads; { std::set<pid_t> siblings; if (!android::procinfo::GetProcessTids(target, &siblings)) { Loading @@ -269,12 +285,12 @@ int main(int argc, char** argv) { if (!ptrace_seize_thread(target_proc_fd, sibling_tid, &attach_error)) { LOG(WARNING) << attach_error; } else { attached_siblings.insert(sibling_tid); threads.emplace(sibling_tid, get_thread_name(sibling_tid)); } } } // Collect the backtrace map and open files, while the process still has PR_GET_DUMPABLE=1 // Collect the backtrace map, open files, and process/thread names, while we still have caps. std::unique_ptr<BacktraceMap> backtrace_map(BacktraceMap::Create(main_tid)); if (!backtrace_map) { LOG(FATAL) << "failed to create backtrace map"; Loading @@ -284,6 +300,9 @@ int main(int argc, char** argv) { OpenFilesList open_files; populate_open_files_list(target, &open_files); std::string process_name = get_process_name(main_tid); threads.emplace(main_tid, get_thread_name(main_tid)); // Drop our capabilities now that we've attached to the threads we care about. drop_capabilities(); Loading Loading @@ -341,10 +360,10 @@ int main(int argc, char** argv) { std::string amfd_data; if (backtrace) { dump_backtrace(output_fd.get(), backtrace_map.get(), target, main_tid, attached_siblings, 0); dump_backtrace(output_fd.get(), backtrace_map.get(), target, main_tid, process_name, threads, 0); } else { engrave_tombstone(output_fd.get(), backtrace_map.get(), &open_files, target, main_tid, &attached_siblings, abort_address, fatal_signal ? &amfd_data : nullptr); process_name, threads, abort_address, fatal_signal ? &amfd_data : nullptr); } // We don't actually need to PTRACE_DETACH, as long as our tracees aren't in Loading debuggerd/libdebuggerd/backtrace.cpp +24 −42 Original line number Diff line number Diff line Loading @@ -38,18 +38,7 @@ #include "utility.h" static void dump_process_header(log_t* log, pid_t pid) { char path[PATH_MAX]; char procnamebuf[1024]; char* procname = NULL; FILE* fp; snprintf(path, sizeof(path), "/proc/%d/cmdline", pid); if ((fp = fopen(path, "r"))) { procname = fgets(procnamebuf, sizeof(procnamebuf), fp); fclose(fp); } static void dump_process_header(log_t* log, pid_t pid, const char* process_name) { time_t t = time(NULL); struct tm tm; localtime_r(&t, &tm); Loading @@ -57,8 +46,8 @@ static void dump_process_header(log_t* log, pid_t pid) { strftime(timestr, sizeof(timestr), "%F %T", &tm); _LOG(log, logtype::BACKTRACE, "\n\n----- pid %d at %s -----\n", pid, timestr); if (procname) { _LOG(log, logtype::BACKTRACE, "Cmd line: %s\n", procname); if (process_name) { _LOG(log, logtype::BACKTRACE, "Cmd line: %s\n", process_name); } _LOG(log, logtype::BACKTRACE, "ABI: '%s'\n", ABI_STRING); } Loading @@ -67,28 +56,13 @@ static void dump_process_footer(log_t* log, pid_t pid) { _LOG(log, logtype::BACKTRACE, "\n----- end %d -----\n", pid); } static void log_thread_name(log_t* log, pid_t tid) { FILE* fp; char buf[1024]; char path[PATH_MAX]; char* threadname = NULL; snprintf(path, sizeof(path), "/proc/%d/comm", tid); if ((fp = fopen(path, "r"))) { threadname = fgets(buf, sizeof(buf), fp); fclose(fp); if (threadname) { size_t len = strlen(threadname); if (len && threadname[len - 1] == '\n') { threadname[len - 1] = '\0'; } } } _LOG(log, logtype::BACKTRACE, "\n\"%s\" sysTid=%d\n", threadname ? threadname : "<unknown>", tid); static void log_thread_name(log_t* log, pid_t tid, const char* thread_name) { _LOG(log, logtype::BACKTRACE, "\n\"%s\" sysTid=%d\n", thread_name, tid); } static void dump_thread(log_t* log, BacktraceMap* map, pid_t pid, pid_t tid) { log_thread_name(log, tid); static void dump_thread(log_t* log, BacktraceMap* map, pid_t pid, pid_t tid, const std::string& thread_name) { log_thread_name(log, tid, thread_name.c_str()); std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid, map)); if (backtrace->Unwind(0)) { Loading @@ -99,17 +73,21 @@ static void dump_thread(log_t* log, BacktraceMap* map, pid_t pid, pid_t tid) { } } void dump_backtrace(int fd, BacktraceMap* map, pid_t pid, pid_t tid, const std::set<pid_t>& siblings, std::string* amfd_data) { void dump_backtrace(int fd, BacktraceMap* map, pid_t pid, pid_t tid, const std::string& process_name, const std::map<pid_t, std::string>& threads, std::string* amfd_data) { log_t log; log.tfd = fd; log.amfd_data = amfd_data; dump_process_header(&log, pid); dump_thread(&log, map, pid, tid); dump_process_header(&log, pid, process_name.c_str()); dump_thread(&log, map, pid, tid, threads.find(tid)->second.c_str()); for (pid_t sibling : siblings) { dump_thread(&log, map, pid, sibling); for (const auto& it : threads) { pid_t thread_tid = it.first; const std::string& thread_name = it.second; if (thread_tid != tid) { dump_thread(&log, map, pid, thread_tid, thread_name.c_str()); } } dump_process_footer(&log, pid); Loading @@ -123,7 +101,9 @@ void dump_backtrace_ucontext(int output_fd, ucontext_t* ucontext) { log.tfd = output_fd; log.amfd_data = nullptr; log_thread_name(&log, tid); char thread_name[16]; read_with_default("/proc/self/comm", thread_name, sizeof(thread_name), "<unknown>"); log_thread_name(&log, tid, thread_name); std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid)); if (backtrace->Unwind(0, ucontext)) { Loading @@ -139,7 +119,9 @@ void dump_backtrace_header(int output_fd) { log.tfd = output_fd; log.amfd_data = nullptr; dump_process_header(&log, getpid()); char process_name[128]; read_with_default("/proc/self/cmdline", process_name, sizeof(process_name), "<unknown>"); dump_process_header(&log, getpid(), process_name); } void dump_backtrace_footer(int output_fd) { Loading debuggerd/libdebuggerd/include/backtrace.h +3 −3 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ #include <sys/types.h> #include <sys/ucontext.h> #include <set> #include <map> #include <string> #include "utility.h" Loading @@ -30,8 +30,8 @@ class BacktraceMap; // Dumps a backtrace using a format similar to what Dalvik uses so that the result // can be intermixed in a bug report. void dump_backtrace(int fd, BacktraceMap* map, pid_t pid, pid_t tid, const std::set<pid_t>& siblings, std::string* amfd_data); void dump_backtrace(int fd, BacktraceMap* map, pid_t pid, pid_t tid, const std::string& process_name, const std::map<pid_t, std::string>& threads, std::string* amfd_data); /* Dumps the backtrace in the backtrace data structure to the log. */ void dump_backtrace_to_log(Backtrace* backtrace, log_t* log, const char* prefix); Loading debuggerd/libdebuggerd/include/tombstone.h +5 −4 Original line number Diff line number Diff line Loading @@ -20,7 +20,8 @@ #include <stdbool.h> #include <stddef.h> #include <sys/types.h> #include <set> #include <map> #include <string> #include "open_files_list.h" Loading @@ -34,9 +35,9 @@ class BacktraceMap; int open_tombstone(std::string* path); /* Creates a tombstone file and writes the crash dump to it. */ void engrave_tombstone(int tombstone_fd, BacktraceMap* map, const OpenFilesList* open_files, pid_t pid, pid_t tid, const std::set<pid_t>* siblings, uintptr_t abort_msg_address, void engrave_tombstone(int tombstone_fd, BacktraceMap* map, const OpenFilesList* open_files, pid_t pid, pid_t tid, const std::string& process_name, const std::map<pid_t, std::string>& threads, uintptr_t abort_msg_address, std::string* amfd_data); void engrave_tombstone_ucontext(int tombstone_fd, uintptr_t abort_msg_address, siginfo_t* siginfo, Loading debuggerd/libdebuggerd/include/utility.h +2 −0 Original line number Diff line number Diff line Loading @@ -83,4 +83,6 @@ bool wait_for_signal(pid_t tid, siginfo_t* siginfo); void dump_memory(log_t* log, Backtrace* backtrace, uintptr_t addr, const char* fmt, ...); void read_with_default(const char* path, char* buf, size_t len, const char* default_value); #endif // _DEBUGGERD_UTILITY_H Loading
debuggerd/crash_dump.cpp +24 −5 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include <unistd.h> #include <limits> #include <map> #include <memory> #include <set> #include <vector> Loading @@ -36,6 +37,7 @@ #include <android-base/parseint.h> #include <android-base/properties.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/unique_fd.h> #include <cutils/sockets.h> #include <log/log.h> Loading @@ -52,7 +54,21 @@ #include "debuggerd/util.h" using android::base::unique_fd; using android::base::ReadFileToString; using android::base::StringPrintf; using android::base::Trim; static std::string get_process_name(pid_t pid) { std::string result = "<unknown>"; ReadFileToString(StringPrintf("/proc/%d/cmdline", pid), &result); return result; } static std::string get_thread_name(pid_t tid) { std::string result = "<unknown>"; ReadFileToString(StringPrintf("/proc/%d/comm", tid), &result); return Trim(result); } static bool pid_contains_tid(int pid_proc_fd, pid_t tid) { struct stat st; Loading Loading @@ -253,7 +269,7 @@ int main(int argc, char** argv) { } // Seize the siblings. std::set<pid_t> attached_siblings; std::map<pid_t, std::string> threads; { std::set<pid_t> siblings; if (!android::procinfo::GetProcessTids(target, &siblings)) { Loading @@ -269,12 +285,12 @@ int main(int argc, char** argv) { if (!ptrace_seize_thread(target_proc_fd, sibling_tid, &attach_error)) { LOG(WARNING) << attach_error; } else { attached_siblings.insert(sibling_tid); threads.emplace(sibling_tid, get_thread_name(sibling_tid)); } } } // Collect the backtrace map and open files, while the process still has PR_GET_DUMPABLE=1 // Collect the backtrace map, open files, and process/thread names, while we still have caps. std::unique_ptr<BacktraceMap> backtrace_map(BacktraceMap::Create(main_tid)); if (!backtrace_map) { LOG(FATAL) << "failed to create backtrace map"; Loading @@ -284,6 +300,9 @@ int main(int argc, char** argv) { OpenFilesList open_files; populate_open_files_list(target, &open_files); std::string process_name = get_process_name(main_tid); threads.emplace(main_tid, get_thread_name(main_tid)); // Drop our capabilities now that we've attached to the threads we care about. drop_capabilities(); Loading Loading @@ -341,10 +360,10 @@ int main(int argc, char** argv) { std::string amfd_data; if (backtrace) { dump_backtrace(output_fd.get(), backtrace_map.get(), target, main_tid, attached_siblings, 0); dump_backtrace(output_fd.get(), backtrace_map.get(), target, main_tid, process_name, threads, 0); } else { engrave_tombstone(output_fd.get(), backtrace_map.get(), &open_files, target, main_tid, &attached_siblings, abort_address, fatal_signal ? &amfd_data : nullptr); process_name, threads, abort_address, fatal_signal ? &amfd_data : nullptr); } // We don't actually need to PTRACE_DETACH, as long as our tracees aren't in Loading
debuggerd/libdebuggerd/backtrace.cpp +24 −42 Original line number Diff line number Diff line Loading @@ -38,18 +38,7 @@ #include "utility.h" static void dump_process_header(log_t* log, pid_t pid) { char path[PATH_MAX]; char procnamebuf[1024]; char* procname = NULL; FILE* fp; snprintf(path, sizeof(path), "/proc/%d/cmdline", pid); if ((fp = fopen(path, "r"))) { procname = fgets(procnamebuf, sizeof(procnamebuf), fp); fclose(fp); } static void dump_process_header(log_t* log, pid_t pid, const char* process_name) { time_t t = time(NULL); struct tm tm; localtime_r(&t, &tm); Loading @@ -57,8 +46,8 @@ static void dump_process_header(log_t* log, pid_t pid) { strftime(timestr, sizeof(timestr), "%F %T", &tm); _LOG(log, logtype::BACKTRACE, "\n\n----- pid %d at %s -----\n", pid, timestr); if (procname) { _LOG(log, logtype::BACKTRACE, "Cmd line: %s\n", procname); if (process_name) { _LOG(log, logtype::BACKTRACE, "Cmd line: %s\n", process_name); } _LOG(log, logtype::BACKTRACE, "ABI: '%s'\n", ABI_STRING); } Loading @@ -67,28 +56,13 @@ static void dump_process_footer(log_t* log, pid_t pid) { _LOG(log, logtype::BACKTRACE, "\n----- end %d -----\n", pid); } static void log_thread_name(log_t* log, pid_t tid) { FILE* fp; char buf[1024]; char path[PATH_MAX]; char* threadname = NULL; snprintf(path, sizeof(path), "/proc/%d/comm", tid); if ((fp = fopen(path, "r"))) { threadname = fgets(buf, sizeof(buf), fp); fclose(fp); if (threadname) { size_t len = strlen(threadname); if (len && threadname[len - 1] == '\n') { threadname[len - 1] = '\0'; } } } _LOG(log, logtype::BACKTRACE, "\n\"%s\" sysTid=%d\n", threadname ? threadname : "<unknown>", tid); static void log_thread_name(log_t* log, pid_t tid, const char* thread_name) { _LOG(log, logtype::BACKTRACE, "\n\"%s\" sysTid=%d\n", thread_name, tid); } static void dump_thread(log_t* log, BacktraceMap* map, pid_t pid, pid_t tid) { log_thread_name(log, tid); static void dump_thread(log_t* log, BacktraceMap* map, pid_t pid, pid_t tid, const std::string& thread_name) { log_thread_name(log, tid, thread_name.c_str()); std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid, map)); if (backtrace->Unwind(0)) { Loading @@ -99,17 +73,21 @@ static void dump_thread(log_t* log, BacktraceMap* map, pid_t pid, pid_t tid) { } } void dump_backtrace(int fd, BacktraceMap* map, pid_t pid, pid_t tid, const std::set<pid_t>& siblings, std::string* amfd_data) { void dump_backtrace(int fd, BacktraceMap* map, pid_t pid, pid_t tid, const std::string& process_name, const std::map<pid_t, std::string>& threads, std::string* amfd_data) { log_t log; log.tfd = fd; log.amfd_data = amfd_data; dump_process_header(&log, pid); dump_thread(&log, map, pid, tid); dump_process_header(&log, pid, process_name.c_str()); dump_thread(&log, map, pid, tid, threads.find(tid)->second.c_str()); for (pid_t sibling : siblings) { dump_thread(&log, map, pid, sibling); for (const auto& it : threads) { pid_t thread_tid = it.first; const std::string& thread_name = it.second; if (thread_tid != tid) { dump_thread(&log, map, pid, thread_tid, thread_name.c_str()); } } dump_process_footer(&log, pid); Loading @@ -123,7 +101,9 @@ void dump_backtrace_ucontext(int output_fd, ucontext_t* ucontext) { log.tfd = output_fd; log.amfd_data = nullptr; log_thread_name(&log, tid); char thread_name[16]; read_with_default("/proc/self/comm", thread_name, sizeof(thread_name), "<unknown>"); log_thread_name(&log, tid, thread_name); std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid)); if (backtrace->Unwind(0, ucontext)) { Loading @@ -139,7 +119,9 @@ void dump_backtrace_header(int output_fd) { log.tfd = output_fd; log.amfd_data = nullptr; dump_process_header(&log, getpid()); char process_name[128]; read_with_default("/proc/self/cmdline", process_name, sizeof(process_name), "<unknown>"); dump_process_header(&log, getpid(), process_name); } void dump_backtrace_footer(int output_fd) { Loading
debuggerd/libdebuggerd/include/backtrace.h +3 −3 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ #include <sys/types.h> #include <sys/ucontext.h> #include <set> #include <map> #include <string> #include "utility.h" Loading @@ -30,8 +30,8 @@ class BacktraceMap; // Dumps a backtrace using a format similar to what Dalvik uses so that the result // can be intermixed in a bug report. void dump_backtrace(int fd, BacktraceMap* map, pid_t pid, pid_t tid, const std::set<pid_t>& siblings, std::string* amfd_data); void dump_backtrace(int fd, BacktraceMap* map, pid_t pid, pid_t tid, const std::string& process_name, const std::map<pid_t, std::string>& threads, std::string* amfd_data); /* Dumps the backtrace in the backtrace data structure to the log. */ void dump_backtrace_to_log(Backtrace* backtrace, log_t* log, const char* prefix); Loading
debuggerd/libdebuggerd/include/tombstone.h +5 −4 Original line number Diff line number Diff line Loading @@ -20,7 +20,8 @@ #include <stdbool.h> #include <stddef.h> #include <sys/types.h> #include <set> #include <map> #include <string> #include "open_files_list.h" Loading @@ -34,9 +35,9 @@ class BacktraceMap; int open_tombstone(std::string* path); /* Creates a tombstone file and writes the crash dump to it. */ void engrave_tombstone(int tombstone_fd, BacktraceMap* map, const OpenFilesList* open_files, pid_t pid, pid_t tid, const std::set<pid_t>* siblings, uintptr_t abort_msg_address, void engrave_tombstone(int tombstone_fd, BacktraceMap* map, const OpenFilesList* open_files, pid_t pid, pid_t tid, const std::string& process_name, const std::map<pid_t, std::string>& threads, uintptr_t abort_msg_address, std::string* amfd_data); void engrave_tombstone_ucontext(int tombstone_fd, uintptr_t abort_msg_address, siginfo_t* siginfo, Loading
debuggerd/libdebuggerd/include/utility.h +2 −0 Original line number Diff line number Diff line Loading @@ -83,4 +83,6 @@ bool wait_for_signal(pid_t tid, siginfo_t* siginfo); void dump_memory(log_t* log, Backtrace* backtrace, uintptr_t addr, const char* fmt, ...); void read_with_default(const char* path, char* buf, size_t len, const char* default_value); #endif // _DEBUGGERD_UTILITY_H