Loading libunwindstack/Unwinder.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -174,7 +174,7 @@ std::string Unwinder::FormatFrame(size_t frame_num) { if (frame_num >= frames_.size()) { return ""; } return FormatFrame(frames_[frame_num], regs_->Arch() == ARCH_ARM || regs_->Arch() == ARCH_X86); return FormatFrame(frames_[frame_num], regs_->Format32Bit()); } std::string Unwinder::FormatFrame(const FrameData& frame, bool bits32) { Loading libunwindstack/include/unwindstack/Regs.h +4 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,8 @@ class Regs { virtual ArchEnum Arch() = 0; virtual bool Format32Bit() = 0; virtual void* RawData() = 0; virtual uint64_t pc() = 0; virtual uint64_t sp() = 0; Loading Loading @@ -92,6 +94,8 @@ class RegsImpl : public Regs { void set_pc(AddressType pc) { pc_ = pc; } void set_sp(AddressType sp) { sp_ = sp; } bool Format32Bit() override { return sizeof(AddressType) == sizeof(uint32_t); } inline AddressType& operator[](size_t reg) { return regs_[reg]; } void* RawData() override { return regs_.data(); } Loading libunwindstack/tests/RegsFake.h +2 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,8 @@ class RegsFake : public Regs { void IterateRegisters(std::function<void(const char*, uint64_t)>) override {} bool Format32Bit() { return false; } uint64_t GetAdjustedPc(uint64_t rel_pc, Elf*) override { return rel_pc - 2; } bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; } Loading libunwindstack/tests/UnwinderTest.cpp +70 −26 Original line number Diff line number Diff line Loading @@ -28,6 +28,10 @@ #include <unwindstack/Maps.h> #include <unwindstack/Memory.h> #include <unwindstack/Regs.h> #include <unwindstack/RegsArm.h> #include <unwindstack/RegsArm64.h> #include <unwindstack/RegsX86.h> #include <unwindstack/RegsX86_64.h> #include <unwindstack/Unwinder.h> #include "ElfFake.h" Loading @@ -53,7 +57,7 @@ class UnwinderTest : public ::testing::Test { static void SetUpTestCase() { maps_.FakeClear(); MapInfo* info = new MapInfo(0x1000, 0x8000, 0, PROT_READ | PROT_WRITE, "/system/fake/libc.so"); ElfFake* elf = new ElfFake(nullptr); ElfFake* elf = new ElfFake(new MemoryFake); info->elf = elf; elf->FakeSetInterface(new ElfInterfaceFake(nullptr)); maps_.FakeAddMapInfo(info); Loading @@ -66,31 +70,33 @@ class UnwinderTest : public ::testing::Test { maps_.FakeAddMapInfo(info); info = new MapInfo(0x20000, 0x22000, 0, PROT_READ | PROT_WRITE, "/system/fake/libunwind.so"); elf = new ElfFake(nullptr); elf = new ElfFake(new MemoryFake); info->elf = elf; elf->FakeSetInterface(new ElfInterfaceFake(nullptr)); maps_.FakeAddMapInfo(info); info = new MapInfo(0x23000, 0x24000, 0, PROT_READ | PROT_WRITE, "/fake/libanother.so"); elf = new ElfFake(nullptr); elf = new ElfFake(new MemoryFake); info->elf = elf; elf->FakeSetInterface(new ElfInterfaceFake(nullptr)); maps_.FakeAddMapInfo(info); info = new MapInfo(0x33000, 0x34000, 0, PROT_READ | PROT_WRITE, "/fake/compressed.so"); elf = new ElfFake(nullptr); elf = new ElfFake(new MemoryFake); info->elf = elf; elf->FakeSetInterface(new ElfInterfaceFake(nullptr)); maps_.FakeAddMapInfo(info); info = new MapInfo(0x43000, 0x44000, 0x1d000, PROT_READ | PROT_WRITE, "/fake/fake.apk"); elf = new ElfFake(nullptr); elf = new ElfFake(new MemoryFake); info->elf = elf; elf->FakeSetInterface(new ElfInterfaceFake(nullptr)); maps_.FakeAddMapInfo(info); info = new MapInfo(0x53000, 0x54000, 0, PROT_READ | PROT_WRITE, "/fake/fake.oat"); maps_.FakeAddMapInfo(info); process_memory_.reset(new MemoryFake); } void SetUp() override { Loading Loading @@ -690,29 +696,67 @@ TEST_F(UnwinderTest, format_frame_static) { EXPECT_EQ(" #01 pc 00001000 <unknown>", Unwinder::FormatFrame(frame, true)); } static std::string ArchToString(ArchEnum arch) { if (arch == ARCH_ARM) { return "Arm"; } else if (arch == ARCH_ARM64) { return "Arm64"; } else if (arch == ARCH_X86) { return "X86"; } else if (arch == ARCH_X86_64) { return "X86_64"; } else { return "Unknown"; } } // Verify format frame code. TEST_F(UnwinderTest, format_frame) { std::vector<Regs*> reg_list; RegsArm* arm = new RegsArm; arm->set_pc(0x2300); arm->set_sp(0x10000); reg_list.push_back(arm); RegsArm64* arm64 = new RegsArm64; arm64->set_pc(0x2300); arm64->set_sp(0x10000); reg_list.push_back(arm64); RegsX86* x86 = new RegsX86; x86->set_pc(0x2300); x86->set_sp(0x10000); reg_list.push_back(x86); RegsX86_64* x86_64 = new RegsX86_64; x86_64->set_pc(0x2300); x86_64->set_sp(0x10000); reg_list.push_back(x86_64); for (auto regs : reg_list) { ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 10)); regs_.FakeSetPc(0x2300); regs_.FakeSetSp(0x10000); Unwinder unwinder(64, &maps_, ®s_, process_memory_); Unwinder unwinder(64, &maps_, regs, process_memory_); unwinder.Unwind(); ASSERT_EQ(1U, unwinder.NumFrames()); regs_.FakeSetArch(ARCH_ARM); EXPECT_EQ(" #00 pc 00001300 /system/fake/libc.so (Frame0+10)", unwinder.FormatFrame(0)); regs_.FakeSetArch(ARCH_X86); EXPECT_EQ(" #00 pc 00001300 /system/fake/libc.so (Frame0+10)", unwinder.FormatFrame(0)); regs_.FakeSetArch(ARCH_ARM64); EXPECT_EQ(" #00 pc 0000000000001300 /system/fake/libc.so (Frame0+10)", unwinder.FormatFrame(0)); regs_.FakeSetArch(ARCH_X86_64); EXPECT_EQ(" #00 pc 0000000000001300 /system/fake/libc.so (Frame0+10)", unwinder.FormatFrame(0)); EXPECT_EQ("", unwinder.FormatFrame(1)); std::string expected; switch (regs->Arch()) { case ARCH_ARM: case ARCH_X86: expected = " #00 pc 00001300 /system/fake/libc.so (Frame0+10)"; break; case ARCH_ARM64: case ARCH_X86_64: expected = " #00 pc 0000000000001300 /system/fake/libc.so (Frame0+10)"; break; default: expected = ""; } EXPECT_EQ(expected, unwinder.FormatFrame(0)) << "Mismatch of frame format for regs arch " << ArchToString(regs->Arch()); delete regs; } } } // namespace unwindstack Loading
libunwindstack/Unwinder.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -174,7 +174,7 @@ std::string Unwinder::FormatFrame(size_t frame_num) { if (frame_num >= frames_.size()) { return ""; } return FormatFrame(frames_[frame_num], regs_->Arch() == ARCH_ARM || regs_->Arch() == ARCH_X86); return FormatFrame(frames_[frame_num], regs_->Format32Bit()); } std::string Unwinder::FormatFrame(const FrameData& frame, bool bits32) { Loading
libunwindstack/include/unwindstack/Regs.h +4 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,8 @@ class Regs { virtual ArchEnum Arch() = 0; virtual bool Format32Bit() = 0; virtual void* RawData() = 0; virtual uint64_t pc() = 0; virtual uint64_t sp() = 0; Loading Loading @@ -92,6 +94,8 @@ class RegsImpl : public Regs { void set_pc(AddressType pc) { pc_ = pc; } void set_sp(AddressType sp) { sp_ = sp; } bool Format32Bit() override { return sizeof(AddressType) == sizeof(uint32_t); } inline AddressType& operator[](size_t reg) { return regs_[reg]; } void* RawData() override { return regs_.data(); } Loading
libunwindstack/tests/RegsFake.h +2 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,8 @@ class RegsFake : public Regs { void IterateRegisters(std::function<void(const char*, uint64_t)>) override {} bool Format32Bit() { return false; } uint64_t GetAdjustedPc(uint64_t rel_pc, Elf*) override { return rel_pc - 2; } bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; } Loading
libunwindstack/tests/UnwinderTest.cpp +70 −26 Original line number Diff line number Diff line Loading @@ -28,6 +28,10 @@ #include <unwindstack/Maps.h> #include <unwindstack/Memory.h> #include <unwindstack/Regs.h> #include <unwindstack/RegsArm.h> #include <unwindstack/RegsArm64.h> #include <unwindstack/RegsX86.h> #include <unwindstack/RegsX86_64.h> #include <unwindstack/Unwinder.h> #include "ElfFake.h" Loading @@ -53,7 +57,7 @@ class UnwinderTest : public ::testing::Test { static void SetUpTestCase() { maps_.FakeClear(); MapInfo* info = new MapInfo(0x1000, 0x8000, 0, PROT_READ | PROT_WRITE, "/system/fake/libc.so"); ElfFake* elf = new ElfFake(nullptr); ElfFake* elf = new ElfFake(new MemoryFake); info->elf = elf; elf->FakeSetInterface(new ElfInterfaceFake(nullptr)); maps_.FakeAddMapInfo(info); Loading @@ -66,31 +70,33 @@ class UnwinderTest : public ::testing::Test { maps_.FakeAddMapInfo(info); info = new MapInfo(0x20000, 0x22000, 0, PROT_READ | PROT_WRITE, "/system/fake/libunwind.so"); elf = new ElfFake(nullptr); elf = new ElfFake(new MemoryFake); info->elf = elf; elf->FakeSetInterface(new ElfInterfaceFake(nullptr)); maps_.FakeAddMapInfo(info); info = new MapInfo(0x23000, 0x24000, 0, PROT_READ | PROT_WRITE, "/fake/libanother.so"); elf = new ElfFake(nullptr); elf = new ElfFake(new MemoryFake); info->elf = elf; elf->FakeSetInterface(new ElfInterfaceFake(nullptr)); maps_.FakeAddMapInfo(info); info = new MapInfo(0x33000, 0x34000, 0, PROT_READ | PROT_WRITE, "/fake/compressed.so"); elf = new ElfFake(nullptr); elf = new ElfFake(new MemoryFake); info->elf = elf; elf->FakeSetInterface(new ElfInterfaceFake(nullptr)); maps_.FakeAddMapInfo(info); info = new MapInfo(0x43000, 0x44000, 0x1d000, PROT_READ | PROT_WRITE, "/fake/fake.apk"); elf = new ElfFake(nullptr); elf = new ElfFake(new MemoryFake); info->elf = elf; elf->FakeSetInterface(new ElfInterfaceFake(nullptr)); maps_.FakeAddMapInfo(info); info = new MapInfo(0x53000, 0x54000, 0, PROT_READ | PROT_WRITE, "/fake/fake.oat"); maps_.FakeAddMapInfo(info); process_memory_.reset(new MemoryFake); } void SetUp() override { Loading Loading @@ -690,29 +696,67 @@ TEST_F(UnwinderTest, format_frame_static) { EXPECT_EQ(" #01 pc 00001000 <unknown>", Unwinder::FormatFrame(frame, true)); } static std::string ArchToString(ArchEnum arch) { if (arch == ARCH_ARM) { return "Arm"; } else if (arch == ARCH_ARM64) { return "Arm64"; } else if (arch == ARCH_X86) { return "X86"; } else if (arch == ARCH_X86_64) { return "X86_64"; } else { return "Unknown"; } } // Verify format frame code. TEST_F(UnwinderTest, format_frame) { std::vector<Regs*> reg_list; RegsArm* arm = new RegsArm; arm->set_pc(0x2300); arm->set_sp(0x10000); reg_list.push_back(arm); RegsArm64* arm64 = new RegsArm64; arm64->set_pc(0x2300); arm64->set_sp(0x10000); reg_list.push_back(arm64); RegsX86* x86 = new RegsX86; x86->set_pc(0x2300); x86->set_sp(0x10000); reg_list.push_back(x86); RegsX86_64* x86_64 = new RegsX86_64; x86_64->set_pc(0x2300); x86_64->set_sp(0x10000); reg_list.push_back(x86_64); for (auto regs : reg_list) { ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 10)); regs_.FakeSetPc(0x2300); regs_.FakeSetSp(0x10000); Unwinder unwinder(64, &maps_, ®s_, process_memory_); Unwinder unwinder(64, &maps_, regs, process_memory_); unwinder.Unwind(); ASSERT_EQ(1U, unwinder.NumFrames()); regs_.FakeSetArch(ARCH_ARM); EXPECT_EQ(" #00 pc 00001300 /system/fake/libc.so (Frame0+10)", unwinder.FormatFrame(0)); regs_.FakeSetArch(ARCH_X86); EXPECT_EQ(" #00 pc 00001300 /system/fake/libc.so (Frame0+10)", unwinder.FormatFrame(0)); regs_.FakeSetArch(ARCH_ARM64); EXPECT_EQ(" #00 pc 0000000000001300 /system/fake/libc.so (Frame0+10)", unwinder.FormatFrame(0)); regs_.FakeSetArch(ARCH_X86_64); EXPECT_EQ(" #00 pc 0000000000001300 /system/fake/libc.so (Frame0+10)", unwinder.FormatFrame(0)); EXPECT_EQ("", unwinder.FormatFrame(1)); std::string expected; switch (regs->Arch()) { case ARCH_ARM: case ARCH_X86: expected = " #00 pc 00001300 /system/fake/libc.so (Frame0+10)"; break; case ARCH_ARM64: case ARCH_X86_64: expected = " #00 pc 0000000000001300 /system/fake/libc.so (Frame0+10)"; break; default: expected = ""; } EXPECT_EQ(expected, unwinder.FormatFrame(0)) << "Mismatch of frame format for regs arch " << ArchToString(regs->Arch()); delete regs; } } } // namespace unwindstack