diff options
author | Christopher Ferris <cferris@google.com> | 2018-03-23 12:51:43 -0700 |
---|---|---|
committer | Christopher Ferris <cferris@google.com> | 2018-03-23 13:01:44 -0700 |
commit | 458f4e725d65e0d400552fbdbefb7d4b19d3c3c5 (patch) | |
tree | 3215275566d5b1f796c087f834ad044592419f7e /libbacktrace | |
parent | 7102f7c98d2aaa393cc6ddc44cf277c5b9b71bf1 (diff) | |
download | system_core-458f4e725d65e0d400552fbdbefb7d4b19d3c3c5.tar.gz system_core-458f4e725d65e0d400552fbdbefb7d4b19d3c3c5.tar.bz2 system_core-458f4e725d65e0d400552fbdbefb7d4b19d3c3c5.zip |
Method to avoid skipping frames for local unwinds.
In cases where there might be a crash in the unwind library itself,
we need a method to avoid skipping these frames or we won't be able
to see the actual crash.
Added unit test for this behavior.
Bug: 74121887
Test: Ran unit tests on host and target.
Change-Id: I45825020c174016af39dd8ffdc67acb72a24ad4d
Diffstat (limited to 'libbacktrace')
-rw-r--r-- | libbacktrace/UnwindStack.cpp | 3 | ||||
-rw-r--r-- | libbacktrace/backtrace_test.cpp | 42 | ||||
-rw-r--r-- | libbacktrace/include/backtrace/Backtrace.h | 6 |
3 files changed, 48 insertions, 3 deletions
diff --git a/libbacktrace/UnwindStack.cpp b/libbacktrace/UnwindStack.cpp index 711a12a6c..e087b2e15 100644 --- a/libbacktrace/UnwindStack.cpp +++ b/libbacktrace/UnwindStack.cpp @@ -163,6 +163,9 @@ bool UnwindStackCurrent::UnwindFromContext(size_t num_ignore_frames, void* ucont } std::vector<std::string> skip_names{"libunwindstack.so", "libbacktrace.so"}; + if (!skip_frames_) { + skip_names.clear(); + } return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames, &skip_names, &error_); } diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp index aab6db9de..1e3d37981 100644 --- a/libbacktrace/backtrace_test.cpp +++ b/libbacktrace/backtrace_test.cpp @@ -69,6 +69,9 @@ // Number of simultaneous threads running in our forked process. #define NUM_PTRACE_THREADS 5 +// The list of shared libaries that make up the backtrace library. +static std::vector<std::string> kBacktraceLibs{"libunwindstack.so", "libbacktrace.so"}; + struct thread_t { pid_t tid; int32_t state; @@ -256,14 +259,47 @@ TEST(libbacktrace, local_no_unwind_frames) { VERIFY_NO_ERROR(backtrace->GetError().error_code); ASSERT_TRUE(backtrace->NumFrames() != 0); + // None of the frames should be in the backtrace libraries. 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()); + for (const auto& lib : kBacktraceLibs) { + ASSERT_TRUE(name != lib) << DumpFrames(backtrace.get()); + } + } + } +} + +TEST(libbacktrace, local_unwind_frames) { + // Verify that a local unwind with the skip frames disabled does include + // frames within the backtrace libraries. + std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), getpid())); + ASSERT_TRUE(backtrace.get() != nullptr); + backtrace->SetSkipFrames(false); + ASSERT_TRUE(backtrace->Unwind(0)); + VERIFY_NO_ERROR(backtrace->GetError().error_code); + + ASSERT_TRUE(backtrace->NumFrames() != 0); + size_t first_frame_non_backtrace_lib = 0; + for (const auto& frame : *backtrace) { + if (BacktraceMap::IsValid(frame.map)) { + const std::string name = basename(frame.map.name.c_str()); + bool found = false; + for (const auto& lib : kBacktraceLibs) { + if (name == lib) { + found = true; + break; + } + } + if (!found) { + first_frame_non_backtrace_lib = frame.num; + break; + } } - break; } + + ASSERT_NE(0U, first_frame_non_backtrace_lib) << "No frames found in backtrace libraries:\n" + << DumpFrames(backtrace.get()); } TEST(libbacktrace, local_trace) { diff --git a/libbacktrace/include/backtrace/Backtrace.h b/libbacktrace/include/backtrace/Backtrace.h index a0882079e..735a2f36e 100644 --- a/libbacktrace/include/backtrace/Backtrace.h +++ b/libbacktrace/include/backtrace/Backtrace.h @@ -204,6 +204,9 @@ class Backtrace { std::string GetErrorString(BacktraceUnwindError error); + // Set whether to skip frames in libbacktrace/libunwindstack when doing a local unwind. + void SetSkipFrames(bool skip_frames) { skip_frames_ = skip_frames; } + protected: Backtrace(pid_t pid, pid_t tid, BacktraceMap* map); @@ -223,6 +226,9 @@ class Backtrace { std::vector<backtrace_frame_data_t> frames_; + // Skip frames in libbacktrace/libunwindstack when doing a local unwind. + bool skip_frames_ = true; + BacktraceUnwindError error_; }; |