diff options
-rw-r--r-- | libbacktrace/UnwindStack.cpp | 1 | ||||
-rw-r--r-- | libbacktrace/include/backtrace/BacktraceMap.h | 8 | ||||
-rw-r--r-- | libunwindstack/Unwinder.cpp | 7 | ||||
-rw-r--r-- | libunwindstack/include/unwindstack/Unwinder.h | 5 | ||||
-rw-r--r-- | libunwindstack/tests/UnwinderTest.cpp | 61 |
5 files changed, 81 insertions, 1 deletions
diff --git a/libbacktrace/UnwindStack.cpp b/libbacktrace/UnwindStack.cpp index 7e2e6d05e..0e32e4740 100644 --- a/libbacktrace/UnwindStack.cpp +++ b/libbacktrace/UnwindStack.cpp @@ -52,6 +52,7 @@ bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map, auto process_memory = stack_map->process_memory(); unwindstack::Unwinder unwinder(MAX_BACKTRACE_FRAMES + num_ignore_frames, stack_map->stack_maps(), regs, stack_map->process_memory()); + unwinder.SetResolveNames(stack_map->ResolveNames()); if (stack_map->GetJitDebug() != nullptr) { unwinder.SetJitDebug(stack_map->GetJitDebug(), regs->Arch()); } diff --git a/libbacktrace/include/backtrace/BacktraceMap.h b/libbacktrace/include/backtrace/BacktraceMap.h index 7b26079cc..da544725d 100644 --- a/libbacktrace/include/backtrace/BacktraceMap.h +++ b/libbacktrace/include/backtrace/BacktraceMap.h @@ -154,6 +154,13 @@ public: const std::vector<std::string>& GetSuffixesToIgnore() { return suffixes_to_ignore_; } + // Disabling the resolving of names results in the function name being + // set to an empty string and the function offset being set to zero + // in the frame data when unwinding. + void SetResolveNames(bool resolve) { resolve_names_ = resolve; } + + bool ResolveNames() { return resolve_names_; } + protected: BacktraceMap(pid_t pid); @@ -164,6 +171,7 @@ public: pid_t pid_; std::deque<backtrace_map_t> maps_; std::vector<std::string> suffixes_to_ignore_; + bool resolve_names_ = true; }; class ScopedBacktraceMapIteratorLock { diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp index d52a0bf99..5a4f5e04c 100644 --- a/libunwindstack/Unwinder.cpp +++ b/libunwindstack/Unwinder.cpp @@ -68,6 +68,10 @@ void Unwinder::FillInDexFrame() { return; } + if (!resolve_names_) { + return; + } + #if !defined(NO_LIBDEXFILE_SUPPORT) if (dex_files_ == nullptr) { return; @@ -100,7 +104,8 @@ void Unwinder::FillInFrame(MapInfo* map_info, Elf* elf, uint64_t adjusted_rel_pc frame->map_flags = map_info->flags; frame->map_load_bias = elf->GetLoadBias(); - if (!elf->GetFunctionName(func_pc, &frame->function_name, &frame->function_offset)) { + if (!resolve_names_ || + !elf->GetFunctionName(func_pc, &frame->function_name, &frame->function_offset)) { frame->function_name = ""; frame->function_offset = 0; } diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h index ebe7b0a5d..5770c1a97 100644 --- a/libunwindstack/include/unwindstack/Unwinder.h +++ b/libunwindstack/include/unwindstack/Unwinder.h @@ -75,6 +75,10 @@ class Unwinder { void SetJitDebug(JitDebug* jit_debug, ArchEnum arch); + // Disabling the resolving of names results in the function name being + // set to an empty string and the function offset being set to zero. + void SetResolveNames(bool resolve) { resolve_names_ = resolve; } + #if !defined(NO_LIBDEXFILE_SUPPORT) void SetDexFiles(DexFiles* dex_files, ArchEnum arch); #endif @@ -95,6 +99,7 @@ class Unwinder { #if !defined(NO_LIBDEXFILE_SUPPORT) DexFiles* dex_files_ = nullptr; #endif + bool resolve_names_ = true; ErrorData last_error_; }; diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp index 7fbae4cf8..e44b225c5 100644 --- a/libunwindstack/tests/UnwinderTest.cpp +++ b/libunwindstack/tests/UnwinderTest.cpp @@ -196,6 +196,67 @@ TEST_F(UnwinderTest, multiple_frames) { EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); } +TEST_F(UnwinderTest, multiple_frames_dont_resolve_names) { + ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); + ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1)); + ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2)); + + regs_.FakeSetPc(0x1000); + regs_.FakeSetSp(0x10000); + ElfInterfaceFake::FakePushStepData(StepData(0x1102, 0x10010, false)); + ElfInterfaceFake::FakePushStepData(StepData(0x1202, 0x10020, false)); + ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); + + Unwinder unwinder(64, &maps_, ®s_, process_memory_); + unwinder.SetResolveNames(false); + unwinder.Unwind(); + EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); + + ASSERT_EQ(3U, unwinder.NumFrames()); + + auto* frame = &unwinder.frames()[0]; + EXPECT_EQ(0U, frame->num); + EXPECT_EQ(0U, frame->rel_pc); + EXPECT_EQ(0x1000U, frame->pc); + EXPECT_EQ(0x10000U, frame->sp); + EXPECT_EQ("", frame->function_name); + EXPECT_EQ(0U, frame->function_offset); + EXPECT_EQ("/system/fake/libc.so", frame->map_name); + EXPECT_EQ(0U, frame->map_offset); + EXPECT_EQ(0x1000U, frame->map_start); + EXPECT_EQ(0x8000U, frame->map_end); + EXPECT_EQ(0U, frame->map_load_bias); + EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); + + frame = &unwinder.frames()[1]; + EXPECT_EQ(1U, frame->num); + EXPECT_EQ(0x100U, frame->rel_pc); + EXPECT_EQ(0x1100U, frame->pc); + EXPECT_EQ(0x10010U, frame->sp); + EXPECT_EQ("", frame->function_name); + EXPECT_EQ(0U, frame->function_offset); + EXPECT_EQ("/system/fake/libc.so", frame->map_name); + EXPECT_EQ(0U, frame->map_offset); + EXPECT_EQ(0x1000U, frame->map_start); + EXPECT_EQ(0x8000U, frame->map_end); + EXPECT_EQ(0U, frame->map_load_bias); + EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); + + frame = &unwinder.frames()[2]; + EXPECT_EQ(2U, frame->num); + EXPECT_EQ(0x200U, frame->rel_pc); + EXPECT_EQ(0x1200U, frame->pc); + EXPECT_EQ(0x10020U, frame->sp); + EXPECT_EQ("", frame->function_name); + EXPECT_EQ(0U, frame->function_offset); + EXPECT_EQ("/system/fake/libc.so", frame->map_name); + EXPECT_EQ(0U, frame->map_offset); + EXPECT_EQ(0x1000U, frame->map_start); + EXPECT_EQ(0x8000U, frame->map_end); + EXPECT_EQ(0U, frame->map_load_bias); + EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); +} + TEST_F(UnwinderTest, non_zero_load_bias) { ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); |