diff options
Diffstat (limited to 'libbacktrace/UnwindCurrent.cpp')
-rwxr-xr-x[-rw-r--r--] | libbacktrace/UnwindCurrent.cpp | 128 |
1 files changed, 51 insertions, 77 deletions
diff --git a/libbacktrace/UnwindCurrent.cpp b/libbacktrace/UnwindCurrent.cpp index 17b71b9..b176aaf 100644..100755 --- a/libbacktrace/UnwindCurrent.cpp +++ b/libbacktrace/UnwindCurrent.cpp @@ -14,9 +14,8 @@ * limitations under the License. */ -#define LOG_TAG "libbacktrace" - #include <sys/types.h> +#include <ucontext.h> #include <backtrace/Backtrace.h> #include <backtrace/BacktraceMap.h> @@ -24,30 +23,11 @@ #define UNW_LOCAL_ONLY #include <libunwind.h> +#include "BacktraceLog.h" +#include "BacktraceThread.h" #include "UnwindCurrent.h" #include "UnwindMap.h" -// Define the ucontext_t structures needed for each supported arch. -#if defined(__arm__) - // The current version of the <signal.h> doesn't define ucontext_t. - #include <asm/sigcontext.h> // Ensure 'struct sigcontext' is defined. - - // Machine context at the time a signal was raised. - typedef struct ucontext { - uint32_t uc_flags; - struct ucontext* uc_link; - stack_t uc_stack; - struct sigcontext uc_mcontext; - uint32_t uc_sigmask; - } ucontext_t; -#elif defined(__i386__) - #include <asm/sigcontext.h> - #include <asm/ucontext.h> - typedef struct ucontext ucontext_t; -#elif !defined(__mips__) && !defined(__aarch64__) - #error Unsupported architecture. -#endif - //------------------------------------------------------------------------- // UnwindCurrent functions. //------------------------------------------------------------------------- @@ -57,13 +37,43 @@ UnwindCurrent::UnwindCurrent() { UnwindCurrent::~UnwindCurrent() { } -bool UnwindCurrent::Unwind(size_t num_ignore_frames) { - int ret = unw_getcontext(&context_); - if (ret < 0) { - BACK_LOGW("unw_getcontext failed %d", ret); - return false; +bool UnwindCurrent::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) { + if (!ucontext) { + int ret = unw_getcontext(&context_); + if (ret < 0) { + BACK_LOGW("unw_getcontext failed %d", ret); + return false; + } } - return UnwindFromContext(num_ignore_frames, true); + else { + GetUnwContextFromUcontext(ucontext); + } + return UnwindFromContext(num_ignore_frames, false); +} + +void UnwindCurrent::GetUnwContextFromUcontext(const ucontext_t* ucontext) { + unw_tdep_context_t* unw_context = reinterpret_cast<unw_tdep_context_t*>(&context_); + +#if defined(__arm__) + unw_context->regs[0] = ucontext->uc_mcontext.arm_r0; + unw_context->regs[1] = ucontext->uc_mcontext.arm_r1; + unw_context->regs[2] = ucontext->uc_mcontext.arm_r2; + unw_context->regs[3] = ucontext->uc_mcontext.arm_r3; + unw_context->regs[4] = ucontext->uc_mcontext.arm_r4; + unw_context->regs[5] = ucontext->uc_mcontext.arm_r5; + unw_context->regs[6] = ucontext->uc_mcontext.arm_r6; + unw_context->regs[7] = ucontext->uc_mcontext.arm_r7; + unw_context->regs[8] = ucontext->uc_mcontext.arm_r8; + unw_context->regs[9] = ucontext->uc_mcontext.arm_r9; + unw_context->regs[10] = ucontext->uc_mcontext.arm_r10; + unw_context->regs[11] = ucontext->uc_mcontext.arm_fp; + unw_context->regs[12] = ucontext->uc_mcontext.arm_ip; + unw_context->regs[13] = ucontext->uc_mcontext.arm_sp; + unw_context->regs[14] = ucontext->uc_mcontext.arm_lr; + unw_context->regs[15] = ucontext->uc_mcontext.arm_pc; +#else + unw_context->uc_mcontext = ucontext->uc_mcontext; +#endif } std::string UnwindCurrent::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) { @@ -78,12 +88,14 @@ std::string UnwindCurrent::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) { return ""; } -bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, bool resolve) { +bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, bool within_handler) { // The cursor structure is pretty large, do not put it on the stack. unw_cursor_t* cursor = new unw_cursor_t; int ret = unw_init_local(cursor, &context_); if (ret < 0) { - BACK_LOGW("unw_init_local failed %d", ret); + if (!within_handler) { + BACK_LOGW("unw_init_local failed %d", ret); + } delete cursor; return false; } @@ -95,13 +107,17 @@ bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, bool resolve) { unw_word_t pc; ret = unw_get_reg(cursor, UNW_REG_IP, &pc); if (ret < 0) { - BACK_LOGW("Failed to read IP %d", ret); + if (!within_handler) { + BACK_LOGW("Failed to read IP %d", ret); + } break; } unw_word_t sp; ret = unw_get_reg(cursor, UNW_REG_SP, &sp); if (ret < 0) { - BACK_LOGW("Failed to read SP %d", ret); + if (!within_handler) { + BACK_LOGW("Failed to read SP %d", ret); + } break; } @@ -119,7 +135,7 @@ bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, bool resolve) { prev->stack_size = frame->sp - prev->sp; } - if (resolve) { + if (!within_handler) { frame->func_name = GetFunctionName(frame->pc, &frame->func_offset); frame->map = FindMap(frame->pc); } else { @@ -137,47 +153,6 @@ bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, bool resolve) { return true; } -void UnwindCurrent::ExtractContext(void* sigcontext) { - unw_tdep_context_t* context = reinterpret_cast<unw_tdep_context_t*>(&context_); - const ucontext_t* uc = reinterpret_cast<const ucontext_t*>(sigcontext); - -#if defined(__arm__) - context->regs[0] = uc->uc_mcontext.arm_r0; - context->regs[1] = uc->uc_mcontext.arm_r1; - context->regs[2] = uc->uc_mcontext.arm_r2; - context->regs[3] = uc->uc_mcontext.arm_r3; - context->regs[4] = uc->uc_mcontext.arm_r4; - context->regs[5] = uc->uc_mcontext.arm_r5; - context->regs[6] = uc->uc_mcontext.arm_r6; - context->regs[7] = uc->uc_mcontext.arm_r7; - context->regs[8] = uc->uc_mcontext.arm_r8; - context->regs[9] = uc->uc_mcontext.arm_r9; - context->regs[10] = uc->uc_mcontext.arm_r10; - context->regs[11] = uc->uc_mcontext.arm_fp; - context->regs[12] = uc->uc_mcontext.arm_ip; - context->regs[13] = uc->uc_mcontext.arm_sp; - context->regs[14] = uc->uc_mcontext.arm_lr; - context->regs[15] = uc->uc_mcontext.arm_pc; -#elif defined(__mips__) || defined(__i386__) - context->uc_mcontext = uc->uc_mcontext; -#endif -} - -//------------------------------------------------------------------------- -// UnwindThread functions. -//------------------------------------------------------------------------- -UnwindThread::UnwindThread() { -} - -UnwindThread::~UnwindThread() { -} - -void UnwindThread::ThreadUnwind( - siginfo_t* /*siginfo*/, void* sigcontext, size_t num_ignore_frames) { - ExtractContext(sigcontext); - UnwindFromContext(num_ignore_frames, false); -} - //------------------------------------------------------------------------- // C++ object creation function. //------------------------------------------------------------------------- @@ -186,6 +161,5 @@ Backtrace* CreateCurrentObj(BacktraceMap* map) { } Backtrace* CreateThreadObj(pid_t tid, BacktraceMap* map) { - UnwindThread* thread_obj = new UnwindThread(); - return new BacktraceThread(thread_obj, thread_obj, tid, map); + return new BacktraceThread(new UnwindCurrent(), tid, map); } |