Loading libbacktrace/BacktraceCurrent.cpp +11 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ * limitations under the License. */ #define _GNU_SOURCE 1 #include <errno.h> #include <stdint.h> #include <string.h> Loading Loading @@ -73,6 +74,16 @@ bool BacktraceCurrent::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) { return UnwindFromContext(num_ignore_frames, nullptr); } bool BacktraceCurrent::DiscardFrame(const backtrace_frame_data_t& frame) { if (BacktraceMap::IsValid(frame.map)) { const std::string library = basename(frame.map.name.c_str()); if (library == "libunwind.so" || library == "libbacktrace.so") { return true; } } return false; } static pthread_mutex_t g_sigaction_mutex = PTHREAD_MUTEX_INITIALIZER; static void SignalHandler(int, siginfo_t*, void* sigcontext) { Loading libbacktrace/BacktraceCurrent.h +3 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,9 @@ public: bool Unwind(size_t num_ignore_frames, ucontext_t* ucontext) override; protected: bool DiscardFrame(const backtrace_frame_data_t& frame); private: bool UnwindThread(size_t num_ignore_frames); Loading libbacktrace/UnwindCurrent.cpp +22 −17 Original line number Diff line number Diff line Loading @@ -99,7 +99,6 @@ bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucon break; } if (num_ignore_frames == 0) { frames_.resize(num_frames+1); backtrace_frame_data_t* frame = &frames_.at(num_frames); frame->num = num_frames; Loading @@ -107,18 +106,24 @@ bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucon frame->sp = static_cast<uintptr_t>(sp); frame->stack_size = 0; FillInMap(frame->pc, &frame->map); // Check to see if we should skip this frame because it's coming // from within the library, and we are doing a local unwind. if (ucontext != nullptr || num_frames != 0 || !DiscardFrame(*frame)) { if (num_ignore_frames == 0) { // GetFunctionName is an expensive call, only do it if we are // keeping the frame. frame->func_name = GetFunctionName(frame->pc, &frame->func_offset); if (num_frames > 0) { // Set the stack size for the previous frame. backtrace_frame_data_t* prev = &frames_.at(num_frames-1); prev->stack_size = frame->sp - prev->sp; } frame->func_name = GetFunctionName(frame->pc, &frame->func_offset); FillInMap(frame->pc, &frame->map); num_frames++; } else { num_ignore_frames--; } } ret = unw_step (cursor.get()); } while (ret > 0 && num_frames < MAX_BACKTRACE_FRAMES); Loading libbacktrace/backtrace_test.cpp +18 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ * limitations under the License. */ #define _GNU_SOURCE 1 #include <dirent.h> #include <errno.h> #include <inttypes.h> Loading Loading @@ -200,6 +201,23 @@ bool WaitForNonZero(int32_t* value, uint64_t seconds) { return false; } TEST(libbacktrace, local_no_unwind_frames) { // Verify that a local unwind does not include any frames within // libunwind or libbacktrace. std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), getpid())); ASSERT_TRUE(backtrace->Unwind(0)); ASSERT_TRUE(backtrace->NumFrames() != 0); for (const auto& frame : *backtrace ) { if (BacktraceMap::IsValid(frame.map)) { const std::string name = basename(frame.map.name.c_str()); ASSERT_TRUE(name != "libunwind.so" && name != "libbacktrace.so") << DumpFrames(backtrace.get()); } break; } } TEST(libbacktrace, local_trace) { ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelBacktrace, nullptr), 0); } Loading Loading
libbacktrace/BacktraceCurrent.cpp +11 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ * limitations under the License. */ #define _GNU_SOURCE 1 #include <errno.h> #include <stdint.h> #include <string.h> Loading Loading @@ -73,6 +74,16 @@ bool BacktraceCurrent::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) { return UnwindFromContext(num_ignore_frames, nullptr); } bool BacktraceCurrent::DiscardFrame(const backtrace_frame_data_t& frame) { if (BacktraceMap::IsValid(frame.map)) { const std::string library = basename(frame.map.name.c_str()); if (library == "libunwind.so" || library == "libbacktrace.so") { return true; } } return false; } static pthread_mutex_t g_sigaction_mutex = PTHREAD_MUTEX_INITIALIZER; static void SignalHandler(int, siginfo_t*, void* sigcontext) { Loading
libbacktrace/BacktraceCurrent.h +3 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,9 @@ public: bool Unwind(size_t num_ignore_frames, ucontext_t* ucontext) override; protected: bool DiscardFrame(const backtrace_frame_data_t& frame); private: bool UnwindThread(size_t num_ignore_frames); Loading
libbacktrace/UnwindCurrent.cpp +22 −17 Original line number Diff line number Diff line Loading @@ -99,7 +99,6 @@ bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucon break; } if (num_ignore_frames == 0) { frames_.resize(num_frames+1); backtrace_frame_data_t* frame = &frames_.at(num_frames); frame->num = num_frames; Loading @@ -107,18 +106,24 @@ bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucon frame->sp = static_cast<uintptr_t>(sp); frame->stack_size = 0; FillInMap(frame->pc, &frame->map); // Check to see if we should skip this frame because it's coming // from within the library, and we are doing a local unwind. if (ucontext != nullptr || num_frames != 0 || !DiscardFrame(*frame)) { if (num_ignore_frames == 0) { // GetFunctionName is an expensive call, only do it if we are // keeping the frame. frame->func_name = GetFunctionName(frame->pc, &frame->func_offset); if (num_frames > 0) { // Set the stack size for the previous frame. backtrace_frame_data_t* prev = &frames_.at(num_frames-1); prev->stack_size = frame->sp - prev->sp; } frame->func_name = GetFunctionName(frame->pc, &frame->func_offset); FillInMap(frame->pc, &frame->map); num_frames++; } else { num_ignore_frames--; } } ret = unw_step (cursor.get()); } while (ret > 0 && num_frames < MAX_BACKTRACE_FRAMES); Loading
libbacktrace/backtrace_test.cpp +18 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ * limitations under the License. */ #define _GNU_SOURCE 1 #include <dirent.h> #include <errno.h> #include <inttypes.h> Loading Loading @@ -200,6 +201,23 @@ bool WaitForNonZero(int32_t* value, uint64_t seconds) { return false; } TEST(libbacktrace, local_no_unwind_frames) { // Verify that a local unwind does not include any frames within // libunwind or libbacktrace. std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), getpid())); ASSERT_TRUE(backtrace->Unwind(0)); ASSERT_TRUE(backtrace->NumFrames() != 0); for (const auto& frame : *backtrace ) { if (BacktraceMap::IsValid(frame.map)) { const std::string name = basename(frame.map.name.c_str()); ASSERT_TRUE(name != "libunwind.so" && name != "libbacktrace.so") << DumpFrames(backtrace.get()); } break; } } TEST(libbacktrace, local_trace) { ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelBacktrace, nullptr), 0); } Loading