Merge "Add ability to skip function name resolution."
This commit is contained in:
commit
2733708cfb
5 changed files with 81 additions and 1 deletions
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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_;
|
||||
};
|
||||
|
||||
|
|
|
@ -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…
Reference in a new issue