Loading debuggerd/backtrace.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -91,7 +91,8 @@ static void dump_thread(log_t* log, BacktraceMap* map, pid_t pid, pid_t tid) { if (backtrace->Unwind(0)) { dump_backtrace_to_log(backtrace.get(), log, " "); } else { ALOGE("Unwind failed: tid = %d", tid); ALOGE("Unwind failed: tid = %d: %s", tid, backtrace->GetErrorString(backtrace->GetError()).c_str()); } } Loading include/backtrace/Backtrace.h +24 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,24 @@ typedef uint64_t word_t; typedef uint32_t word_t; #endif enum BacktraceUnwindError : uint32_t { BACKTRACE_UNWIND_NO_ERROR, // Something failed while trying to perform the setup to begin the unwind. BACKTRACE_UNWIND_ERROR_SETUP_FAILED, // There is no map information to use with the unwind. BACKTRACE_UNWIND_ERROR_MAP_MISSING, // An error occurred that indicates a programming error. BACKTRACE_UNWIND_ERROR_INTERNAL, // The thread to unwind has disappeared before the unwind can begin. BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST, // The thread to unwind has not responded to a signal in a timely manner. BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT, // Attempt to do an unsupported operation. BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION, // Attempt to do an offline unwind without a context. BACKTRACE_UNWIND_ERROR_NO_CONTEXT, }; struct backtrace_frame_data_t { size_t num; // The current fame number. uintptr_t pc; // The absolute pc. Loading Loading @@ -127,6 +145,10 @@ public: BacktraceMap* GetMap() { return map_; } BacktraceUnwindError GetError() { return error_; } std::string GetErrorString(BacktraceUnwindError error); protected: Backtrace(pid_t pid, pid_t tid, BacktraceMap* map); Loading @@ -145,6 +167,8 @@ protected: bool map_shared_; std::vector<backtrace_frame_data_t> frames_; BacktraceUnwindError error_; }; #endif // _BACKTRACE_BACKTRACE_H libbacktrace/Backtrace.cpp +21 −0 Original line number Diff line number Diff line Loading @@ -148,3 +148,24 @@ Backtrace* Backtrace::Create(pid_t pid, pid_t tid, BacktraceMap* map) { return new UnwindPtrace(pid, tid, map); } } std::string Backtrace::GetErrorString(BacktraceUnwindError error) { switch (error) { case BACKTRACE_UNWIND_NO_ERROR: return "No error"; case BACKTRACE_UNWIND_ERROR_SETUP_FAILED: return "Setup failed"; case BACKTRACE_UNWIND_ERROR_MAP_MISSING: return "No map found"; case BACKTRACE_UNWIND_ERROR_INTERNAL: return "Internal libbacktrace error, please submit a bugreport"; case BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST: return "Thread doesn't exist"; case BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT: return "Thread has not repsonded to signal in time"; case BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION: return "Attempt to use an unsupported feature"; case BACKTRACE_UNWIND_ERROR_NO_CONTEXT: return "Attempt to do an offline unwind without a context"; } } libbacktrace/BacktraceCurrent.cpp +20 −2 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ #include <ucontext.h> #include <unistd.h> #include <stdlib.h> #include <string> #include <backtrace/Backtrace.h> Loading Loading @@ -65,9 +67,11 @@ size_t BacktraceCurrent::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) { bool BacktraceCurrent::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) { if (GetMap() == nullptr) { // Without a map object, we can't do anything. error_ = BACKTRACE_UNWIND_ERROR_MAP_MISSING; return false; } error_ = BACKTRACE_UNWIND_NO_ERROR; if (ucontext) { return UnwindFromContext(num_ignore_frames, ucontext); } Loading Loading @@ -138,11 +142,19 @@ bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) { BACK_LOGE("sigaction failed: %s", strerror(errno)); ThreadEntry::Remove(entry); pthread_mutex_unlock(&g_sigaction_mutex); error_ = BACKTRACE_UNWIND_ERROR_INTERNAL; return false; } if (tgkill(Pid(), Tid(), THREAD_SIGNAL) != 0) { BACK_LOGE("tgkill %d failed: %s", Tid(), strerror(errno)); // Do not emit an error message, this might be expected. Set the // error and let the caller decide. if (errno == ESRCH) { error_ = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST; } else { error_ = BACKTRACE_UNWIND_ERROR_INTERNAL; } sigaction(THREAD_SIGNAL, &oldact, nullptr); ThreadEntry::Remove(entry); pthread_mutex_unlock(&g_sigaction_mutex); Loading Loading @@ -183,8 +195,14 @@ bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) { BACK_LOGW("Timed out waiting for signal handler to indicate it finished."); } } else { // Check to see if the thread has disappeared. if (tgkill(Pid(), Tid(), 0) == -1 && errno == ESRCH) { error_ = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST; } else { error_ = BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT; BACK_LOGE("Timed out waiting for signal handler to get ucontext data."); } } ThreadEntry::Remove(entry); Loading libbacktrace/BacktraceOffline.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -129,9 +129,11 @@ static unw_accessors_t accessors = { bool BacktraceOffline::Unwind(size_t num_ignore_frames, ucontext_t* context) { if (context == nullptr) { BACK_LOGW("The context is needed for offline backtracing."); error_ = BACKTRACE_UNWIND_ERROR_NO_CONTEXT; return false; } context_ = context; error_ = BACKTRACE_UNWIND_NO_ERROR; unw_addr_space_t addr_space = unw_create_addr_space(&accessors, 0); unw_cursor_t cursor; Loading @@ -139,6 +141,7 @@ bool BacktraceOffline::Unwind(size_t num_ignore_frames, ucontext_t* context) { if (ret != 0) { BACK_LOGW("unw_init_remote failed %d", ret); unw_destroy_addr_space(addr_space); error_ = BACKTRACE_UNWIND_ERROR_SETUP_FAILED; return false; } size_t num_frames = 0; Loading Loading
debuggerd/backtrace.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -91,7 +91,8 @@ static void dump_thread(log_t* log, BacktraceMap* map, pid_t pid, pid_t tid) { if (backtrace->Unwind(0)) { dump_backtrace_to_log(backtrace.get(), log, " "); } else { ALOGE("Unwind failed: tid = %d", tid); ALOGE("Unwind failed: tid = %d: %s", tid, backtrace->GetErrorString(backtrace->GetError()).c_str()); } } Loading
include/backtrace/Backtrace.h +24 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,24 @@ typedef uint64_t word_t; typedef uint32_t word_t; #endif enum BacktraceUnwindError : uint32_t { BACKTRACE_UNWIND_NO_ERROR, // Something failed while trying to perform the setup to begin the unwind. BACKTRACE_UNWIND_ERROR_SETUP_FAILED, // There is no map information to use with the unwind. BACKTRACE_UNWIND_ERROR_MAP_MISSING, // An error occurred that indicates a programming error. BACKTRACE_UNWIND_ERROR_INTERNAL, // The thread to unwind has disappeared before the unwind can begin. BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST, // The thread to unwind has not responded to a signal in a timely manner. BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT, // Attempt to do an unsupported operation. BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION, // Attempt to do an offline unwind without a context. BACKTRACE_UNWIND_ERROR_NO_CONTEXT, }; struct backtrace_frame_data_t { size_t num; // The current fame number. uintptr_t pc; // The absolute pc. Loading Loading @@ -127,6 +145,10 @@ public: BacktraceMap* GetMap() { return map_; } BacktraceUnwindError GetError() { return error_; } std::string GetErrorString(BacktraceUnwindError error); protected: Backtrace(pid_t pid, pid_t tid, BacktraceMap* map); Loading @@ -145,6 +167,8 @@ protected: bool map_shared_; std::vector<backtrace_frame_data_t> frames_; BacktraceUnwindError error_; }; #endif // _BACKTRACE_BACKTRACE_H
libbacktrace/Backtrace.cpp +21 −0 Original line number Diff line number Diff line Loading @@ -148,3 +148,24 @@ Backtrace* Backtrace::Create(pid_t pid, pid_t tid, BacktraceMap* map) { return new UnwindPtrace(pid, tid, map); } } std::string Backtrace::GetErrorString(BacktraceUnwindError error) { switch (error) { case BACKTRACE_UNWIND_NO_ERROR: return "No error"; case BACKTRACE_UNWIND_ERROR_SETUP_FAILED: return "Setup failed"; case BACKTRACE_UNWIND_ERROR_MAP_MISSING: return "No map found"; case BACKTRACE_UNWIND_ERROR_INTERNAL: return "Internal libbacktrace error, please submit a bugreport"; case BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST: return "Thread doesn't exist"; case BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT: return "Thread has not repsonded to signal in time"; case BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION: return "Attempt to use an unsupported feature"; case BACKTRACE_UNWIND_ERROR_NO_CONTEXT: return "Attempt to do an offline unwind without a context"; } }
libbacktrace/BacktraceCurrent.cpp +20 −2 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ #include <ucontext.h> #include <unistd.h> #include <stdlib.h> #include <string> #include <backtrace/Backtrace.h> Loading Loading @@ -65,9 +67,11 @@ size_t BacktraceCurrent::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) { bool BacktraceCurrent::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) { if (GetMap() == nullptr) { // Without a map object, we can't do anything. error_ = BACKTRACE_UNWIND_ERROR_MAP_MISSING; return false; } error_ = BACKTRACE_UNWIND_NO_ERROR; if (ucontext) { return UnwindFromContext(num_ignore_frames, ucontext); } Loading Loading @@ -138,11 +142,19 @@ bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) { BACK_LOGE("sigaction failed: %s", strerror(errno)); ThreadEntry::Remove(entry); pthread_mutex_unlock(&g_sigaction_mutex); error_ = BACKTRACE_UNWIND_ERROR_INTERNAL; return false; } if (tgkill(Pid(), Tid(), THREAD_SIGNAL) != 0) { BACK_LOGE("tgkill %d failed: %s", Tid(), strerror(errno)); // Do not emit an error message, this might be expected. Set the // error and let the caller decide. if (errno == ESRCH) { error_ = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST; } else { error_ = BACKTRACE_UNWIND_ERROR_INTERNAL; } sigaction(THREAD_SIGNAL, &oldact, nullptr); ThreadEntry::Remove(entry); pthread_mutex_unlock(&g_sigaction_mutex); Loading Loading @@ -183,8 +195,14 @@ bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) { BACK_LOGW("Timed out waiting for signal handler to indicate it finished."); } } else { // Check to see if the thread has disappeared. if (tgkill(Pid(), Tid(), 0) == -1 && errno == ESRCH) { error_ = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST; } else { error_ = BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT; BACK_LOGE("Timed out waiting for signal handler to get ucontext data."); } } ThreadEntry::Remove(entry); Loading
libbacktrace/BacktraceOffline.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -129,9 +129,11 @@ static unw_accessors_t accessors = { bool BacktraceOffline::Unwind(size_t num_ignore_frames, ucontext_t* context) { if (context == nullptr) { BACK_LOGW("The context is needed for offline backtracing."); error_ = BACKTRACE_UNWIND_ERROR_NO_CONTEXT; return false; } context_ = context; error_ = BACKTRACE_UNWIND_NO_ERROR; unw_addr_space_t addr_space = unw_create_addr_space(&accessors, 0); unw_cursor_t cursor; Loading @@ -139,6 +141,7 @@ bool BacktraceOffline::Unwind(size_t num_ignore_frames, ucontext_t* context) { if (ret != 0) { BACK_LOGW("unw_init_remote failed %d", ret); unw_destroy_addr_space(addr_space); error_ = BACKTRACE_UNWIND_ERROR_SETUP_FAILED; return false; } size_t num_frames = 0; Loading