Loading libbacktrace/UnwindStack.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -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()); } Loading libbacktrace/include/backtrace/BacktraceMap.h +8 −0 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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 { Loading libunwindstack/Unwinder.cpp +6 −1 Original line number Diff line number Diff line Loading @@ -68,6 +68,10 @@ void Unwinder::FillInDexFrame() { return; } if (!resolve_names_) { return; } #if !defined(NO_LIBDEXFILE_SUPPORT) if (dex_files_ == nullptr) { return; Loading Loading @@ -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; } Loading libunwindstack/include/unwindstack/Unwinder.h +5 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -95,6 +99,7 @@ class Unwinder { #if !defined(NO_LIBDEXFILE_SUPPORT) DexFiles* dex_files_ = nullptr; #endif bool resolve_names_ = true; ErrorData last_error_; }; Loading libunwindstack/tests/UnwinderTest.cpp +61 −0 Original line number Diff line number Diff line Loading @@ -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)); Loading Loading
libbacktrace/UnwindStack.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -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()); } Loading
libbacktrace/include/backtrace/BacktraceMap.h +8 −0 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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 { Loading
libunwindstack/Unwinder.cpp +6 −1 Original line number Diff line number Diff line Loading @@ -68,6 +68,10 @@ void Unwinder::FillInDexFrame() { return; } if (!resolve_names_) { return; } #if !defined(NO_LIBDEXFILE_SUPPORT) if (dex_files_ == nullptr) { return; Loading Loading @@ -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; } Loading
libunwindstack/include/unwindstack/Unwinder.h +5 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -95,6 +99,7 @@ class Unwinder { #if !defined(NO_LIBDEXFILE_SUPPORT) DexFiles* dex_files_ = nullptr; #endif bool resolve_names_ = true; ErrorData last_error_; }; Loading
libunwindstack/tests/UnwinderTest.cpp +61 −0 Original line number Diff line number Diff line Loading @@ -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)); Loading