Loading libunwindstack/Unwinder.cpp +12 −7 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ void Unwinder::FillInDexFrame() { frame->sp = regs_->sp(); MapInfo* info = maps_->Find(dex_pc); if (info != nullptr) { frame->map_start = info->start; frame->map_end = info->end; frame->map_offset = info->offset; Loading @@ -61,6 +62,10 @@ void Unwinder::FillInDexFrame() { frame->map_flags = info->flags; frame->map_name = info->name; frame->rel_pc = dex_pc - info->start; } else { frame->rel_pc = dex_pc; return; } #if !defined(NO_LIBDEXFILE_SUPPORT) if (dex_files_ == nullptr) { Loading libunwindstack/include/unwindstack/Unwinder.h +6 −6 Original line number Diff line number Diff line Loading @@ -45,14 +45,14 @@ struct FrameData { uint64_t sp; std::string function_name; uint64_t function_offset; uint64_t function_offset = 0; std::string map_name; uint64_t map_offset; uint64_t map_start; uint64_t map_end; uint64_t map_load_bias; int map_flags; uint64_t map_offset = 0; uint64_t map_start = 0; uint64_t map_end = 0; uint64_t map_load_bias = 0; int map_flags = 0; }; class Unwinder { Loading libunwindstack/tests/RegsFake.h +1 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ class RegsFake : public Regs { void FakeSetArch(ArchEnum arch) { fake_arch_ = arch; } void FakeSetPc(uint64_t pc) { fake_pc_ = pc; } void FakeSetSp(uint64_t sp) { fake_sp_ = sp; } void FakeSetDexPc(uint64_t dex_pc) { dex_pc_ = dex_pc; } void FakeSetReturnAddress(uint64_t return_address) { fake_return_address_ = return_address; } void FakeSetReturnAddressValid(bool valid) { fake_return_address_valid_ = valid; } Loading libunwindstack/tests/UnwinderTest.cpp +86 −0 Original line number Diff line number Diff line Loading @@ -98,6 +98,10 @@ class UnwinderTest : public ::testing::Test { info = new MapInfo(0x53000, 0x54000, 0, PROT_READ | PROT_WRITE, "/fake/fake.oat"); maps_.FakeAddMapInfo(info); info = new MapInfo(0xa3000, 0xa4000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/fake.vdex"); info->load_bias = 0; maps_.FakeAddMapInfo(info); process_memory_.reset(new MemoryFake); } Loading Loading @@ -666,6 +670,88 @@ TEST_F(UnwinderTest, sp_pc_do_not_change) { EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); } TEST_F(UnwinderTest, dex_pc_in_map) { ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); regs_.FakeSetPc(0x1000); regs_.FakeSetSp(0x10000); regs_.FakeSetDexPc(0xa3400); Unwinder unwinder(64, &maps_, ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); ASSERT_EQ(2U, unwinder.NumFrames()); auto* frame = &unwinder.frames()[0]; EXPECT_EQ(0U, frame->num); EXPECT_EQ(0x400U, frame->rel_pc); EXPECT_EQ(0xa3400U, frame->pc); EXPECT_EQ(0x10000U, frame->sp); EXPECT_EQ("", frame->function_name); EXPECT_EQ(0U, frame->function_offset); EXPECT_EQ("/fake/fake.vdex", frame->map_name); EXPECT_EQ(0U, frame->map_offset); EXPECT_EQ(0xa3000U, frame->map_start); EXPECT_EQ(0xa4000U, frame->map_end); EXPECT_EQ(0U, frame->map_load_bias); EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags); frame = &unwinder.frames()[1]; EXPECT_EQ(1U, frame->num); EXPECT_EQ(0U, frame->rel_pc); EXPECT_EQ(0x1000U, frame->pc); EXPECT_EQ(0x10000U, frame->sp); EXPECT_EQ("Frame0", 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, dex_pc_not_in_map) { ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); regs_.FakeSetPc(0x1000); regs_.FakeSetSp(0x10000); regs_.FakeSetDexPc(0x50000); Unwinder unwinder(64, &maps_, ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); ASSERT_EQ(2U, unwinder.NumFrames()); auto* frame = &unwinder.frames()[0]; EXPECT_EQ(0U, frame->num); EXPECT_EQ(0x50000U, frame->rel_pc); EXPECT_EQ(0x50000U, frame->pc); EXPECT_EQ(0x10000U, frame->sp); EXPECT_EQ("", frame->function_name); EXPECT_EQ(0U, frame->function_offset); EXPECT_EQ("", frame->map_name); EXPECT_EQ(0U, frame->map_offset); EXPECT_EQ(0U, frame->map_start); EXPECT_EQ(0U, frame->map_end); EXPECT_EQ(0U, frame->map_load_bias); EXPECT_EQ(0, frame->map_flags); frame = &unwinder.frames()[1]; EXPECT_EQ(1U, frame->num); EXPECT_EQ(0U, frame->rel_pc); EXPECT_EQ(0x1000U, frame->pc); EXPECT_EQ(0x10000U, frame->sp); EXPECT_EQ("Frame0", 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); } // Verify format frame code. TEST_F(UnwinderTest, format_frame_static) { FrameData frame; Loading Loading
libunwindstack/Unwinder.cpp +12 −7 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ void Unwinder::FillInDexFrame() { frame->sp = regs_->sp(); MapInfo* info = maps_->Find(dex_pc); if (info != nullptr) { frame->map_start = info->start; frame->map_end = info->end; frame->map_offset = info->offset; Loading @@ -61,6 +62,10 @@ void Unwinder::FillInDexFrame() { frame->map_flags = info->flags; frame->map_name = info->name; frame->rel_pc = dex_pc - info->start; } else { frame->rel_pc = dex_pc; return; } #if !defined(NO_LIBDEXFILE_SUPPORT) if (dex_files_ == nullptr) { Loading
libunwindstack/include/unwindstack/Unwinder.h +6 −6 Original line number Diff line number Diff line Loading @@ -45,14 +45,14 @@ struct FrameData { uint64_t sp; std::string function_name; uint64_t function_offset; uint64_t function_offset = 0; std::string map_name; uint64_t map_offset; uint64_t map_start; uint64_t map_end; uint64_t map_load_bias; int map_flags; uint64_t map_offset = 0; uint64_t map_start = 0; uint64_t map_end = 0; uint64_t map_load_bias = 0; int map_flags = 0; }; class Unwinder { Loading
libunwindstack/tests/RegsFake.h +1 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ class RegsFake : public Regs { void FakeSetArch(ArchEnum arch) { fake_arch_ = arch; } void FakeSetPc(uint64_t pc) { fake_pc_ = pc; } void FakeSetSp(uint64_t sp) { fake_sp_ = sp; } void FakeSetDexPc(uint64_t dex_pc) { dex_pc_ = dex_pc; } void FakeSetReturnAddress(uint64_t return_address) { fake_return_address_ = return_address; } void FakeSetReturnAddressValid(bool valid) { fake_return_address_valid_ = valid; } Loading
libunwindstack/tests/UnwinderTest.cpp +86 −0 Original line number Diff line number Diff line Loading @@ -98,6 +98,10 @@ class UnwinderTest : public ::testing::Test { info = new MapInfo(0x53000, 0x54000, 0, PROT_READ | PROT_WRITE, "/fake/fake.oat"); maps_.FakeAddMapInfo(info); info = new MapInfo(0xa3000, 0xa4000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/fake.vdex"); info->load_bias = 0; maps_.FakeAddMapInfo(info); process_memory_.reset(new MemoryFake); } Loading Loading @@ -666,6 +670,88 @@ TEST_F(UnwinderTest, sp_pc_do_not_change) { EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); } TEST_F(UnwinderTest, dex_pc_in_map) { ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); regs_.FakeSetPc(0x1000); regs_.FakeSetSp(0x10000); regs_.FakeSetDexPc(0xa3400); Unwinder unwinder(64, &maps_, ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); ASSERT_EQ(2U, unwinder.NumFrames()); auto* frame = &unwinder.frames()[0]; EXPECT_EQ(0U, frame->num); EXPECT_EQ(0x400U, frame->rel_pc); EXPECT_EQ(0xa3400U, frame->pc); EXPECT_EQ(0x10000U, frame->sp); EXPECT_EQ("", frame->function_name); EXPECT_EQ(0U, frame->function_offset); EXPECT_EQ("/fake/fake.vdex", frame->map_name); EXPECT_EQ(0U, frame->map_offset); EXPECT_EQ(0xa3000U, frame->map_start); EXPECT_EQ(0xa4000U, frame->map_end); EXPECT_EQ(0U, frame->map_load_bias); EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags); frame = &unwinder.frames()[1]; EXPECT_EQ(1U, frame->num); EXPECT_EQ(0U, frame->rel_pc); EXPECT_EQ(0x1000U, frame->pc); EXPECT_EQ(0x10000U, frame->sp); EXPECT_EQ("Frame0", 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, dex_pc_not_in_map) { ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); regs_.FakeSetPc(0x1000); regs_.FakeSetSp(0x10000); regs_.FakeSetDexPc(0x50000); Unwinder unwinder(64, &maps_, ®s_, process_memory_); unwinder.Unwind(); EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); ASSERT_EQ(2U, unwinder.NumFrames()); auto* frame = &unwinder.frames()[0]; EXPECT_EQ(0U, frame->num); EXPECT_EQ(0x50000U, frame->rel_pc); EXPECT_EQ(0x50000U, frame->pc); EXPECT_EQ(0x10000U, frame->sp); EXPECT_EQ("", frame->function_name); EXPECT_EQ(0U, frame->function_offset); EXPECT_EQ("", frame->map_name); EXPECT_EQ(0U, frame->map_offset); EXPECT_EQ(0U, frame->map_start); EXPECT_EQ(0U, frame->map_end); EXPECT_EQ(0U, frame->map_load_bias); EXPECT_EQ(0, frame->map_flags); frame = &unwinder.frames()[1]; EXPECT_EQ(1U, frame->num); EXPECT_EQ(0U, frame->rel_pc); EXPECT_EQ(0x1000U, frame->pc); EXPECT_EQ(0x10000U, frame->sp); EXPECT_EQ("Frame0", 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); } // Verify format frame code. TEST_F(UnwinderTest, format_frame_static) { FrameData frame; Loading