summaryrefslogtreecommitdiffstats
path: root/libbacktrace
diff options
context:
space:
mode:
authorChristopher Ferris <cferris@google.com>2018-03-23 12:51:43 -0700
committerChristopher Ferris <cferris@google.com>2018-03-23 13:01:44 -0700
commit458f4e725d65e0d400552fbdbefb7d4b19d3c3c5 (patch)
tree3215275566d5b1f796c087f834ad044592419f7e /libbacktrace
parent7102f7c98d2aaa393cc6ddc44cf277c5b9b71bf1 (diff)
downloadsystem_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.cpp3
-rw-r--r--libbacktrace/backtrace_test.cpp42
-rw-r--r--libbacktrace/include/backtrace/Backtrace.h6
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_;
};