diff options
author | Christopher Ferris <cferris@google.com> | 2018-02-20 13:58:40 -0800 |
---|---|---|
committer | Christopher Ferris <cferris@google.com> | 2018-02-20 17:10:23 -0800 |
commit | 821bb2e94f37c2c2a35952366f92962f2999e9e0 (patch) | |
tree | d89fa3248e1f6bf2bb768a97b9d67edaeafe00c2 | |
parent | d162ef6c6753e70f6ffb83df451d308c31bd57bf (diff) | |
download | unwinding-821bb2e94f37c2c2a35952366f92962f2999e9e0.tar.gz |
Add ability to skip function name resolution.
Bug: 73558129
Test: New unit tests pass.
Change-Id: I3a6b17d2590aacb367ab3e3a51cc85be73ad64eb
-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 7e2e6d0..0e32e47 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 7b26079..da54472 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 d52a0bf..5a4f5e0 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 ebe7b0a..5770c1a 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 7fbae4c..e44b225 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)); |