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
(cherry picked from commit 458f4e725d
)
This commit is contained in:
parent
677bed578e
commit
af16967ec8
|
@ -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_);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,16 +259,49 @@ 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());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_NE(0U, first_frame_non_backtrace_lib) << "No frames found in backtrace libraries:\n"
|
||||
<< DumpFrames(backtrace.get());
|
||||
}
|
||||
|
||||
TEST(libbacktrace, local_trace) {
|
||||
ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelBacktrace, nullptr), 0);
|
||||
}
|
||||
|
|
|
@ -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_;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue