Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 02fdb569 authored by Christopher Ferris's avatar Christopher Ferris
Browse files

Do not check arch for format check.

Use a generic check if the address is 32 bits when using the default
formating of a backtrace line instead of an arch check.

Test: New unit tests pass.
Change-Id: Id609abc037d7b437a02d52763aa91fbefe5f4d5b
parent a4a9a81d
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -174,7 +174,7 @@ std::string Unwinder::FormatFrame(size_t frame_num) {
  if (frame_num >= frames_.size()) {
  if (frame_num >= frames_.size()) {
    return "";
    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) {
std::string Unwinder::FormatFrame(const FrameData& frame, bool bits32) {
+4 −0
Original line number Original line Diff line number Diff line
@@ -51,6 +51,8 @@ class Regs {


  virtual ArchEnum Arch() = 0;
  virtual ArchEnum Arch() = 0;


  virtual bool Format32Bit() = 0;

  virtual void* RawData() = 0;
  virtual void* RawData() = 0;
  virtual uint64_t pc() = 0;
  virtual uint64_t pc() = 0;
  virtual uint64_t sp() = 0;
  virtual uint64_t sp() = 0;
@@ -92,6 +94,8 @@ class RegsImpl : public Regs {
  void set_pc(AddressType pc) { pc_ = pc; }
  void set_pc(AddressType pc) { pc_ = pc; }
  void set_sp(AddressType sp) { sp_ = sp; }
  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]; }
  inline AddressType& operator[](size_t reg) { return regs_[reg]; }


  void* RawData() override { return regs_.data(); }
  void* RawData() override { return regs_.data(); }
+2 −0
Original line number Original line Diff line number Diff line
@@ -45,6 +45,8 @@ class RegsFake : public Regs {


  void IterateRegisters(std::function<void(const char*, uint64_t)>) override {}
  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; }
  uint64_t GetAdjustedPc(uint64_t rel_pc, Elf*) override { return rel_pc - 2; }


  bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; }
  bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; }
+70 −26
Original line number Original line Diff line number Diff line
@@ -28,6 +28,10 @@
#include <unwindstack/Maps.h>
#include <unwindstack/Maps.h>
#include <unwindstack/Memory.h>
#include <unwindstack/Memory.h>
#include <unwindstack/Regs.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 <unwindstack/Unwinder.h>


#include "ElfFake.h"
#include "ElfFake.h"
@@ -53,7 +57,7 @@ class UnwinderTest : public ::testing::Test {
  static void SetUpTestCase() {
  static void SetUpTestCase() {
    maps_.FakeClear();
    maps_.FakeClear();
    MapInfo* info = new MapInfo(0x1000, 0x8000, 0, PROT_READ | PROT_WRITE, "/system/fake/libc.so");
    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;
    info->elf = elf;
    elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
    elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
    maps_.FakeAddMapInfo(info);
    maps_.FakeAddMapInfo(info);
@@ -66,31 +70,33 @@ class UnwinderTest : public ::testing::Test {
    maps_.FakeAddMapInfo(info);
    maps_.FakeAddMapInfo(info);


    info = new MapInfo(0x20000, 0x22000, 0, PROT_READ | PROT_WRITE, "/system/fake/libunwind.so");
    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;
    info->elf = elf;
    elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
    elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
    maps_.FakeAddMapInfo(info);
    maps_.FakeAddMapInfo(info);


    info = new MapInfo(0x23000, 0x24000, 0, PROT_READ | PROT_WRITE, "/fake/libanother.so");
    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;
    info->elf = elf;
    elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
    elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
    maps_.FakeAddMapInfo(info);
    maps_.FakeAddMapInfo(info);


    info = new MapInfo(0x33000, 0x34000, 0, PROT_READ | PROT_WRITE, "/fake/compressed.so");
    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;
    info->elf = elf;
    elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
    elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
    maps_.FakeAddMapInfo(info);
    maps_.FakeAddMapInfo(info);


    info = new MapInfo(0x43000, 0x44000, 0x1d000, PROT_READ | PROT_WRITE, "/fake/fake.apk");
    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;
    info->elf = elf;
    elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
    elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
    maps_.FakeAddMapInfo(info);
    maps_.FakeAddMapInfo(info);


    info = new MapInfo(0x53000, 0x54000, 0, PROT_READ | PROT_WRITE, "/fake/fake.oat");
    info = new MapInfo(0x53000, 0x54000, 0, PROT_READ | PROT_WRITE, "/fake/fake.oat");
    maps_.FakeAddMapInfo(info);
    maps_.FakeAddMapInfo(info);

    process_memory_.reset(new MemoryFake);
  }
  }


  void SetUp() override {
  void SetUp() override {
@@ -690,29 +696,67 @@ TEST_F(UnwinderTest, format_frame_static) {
  EXPECT_EQ("  #01 pc 00001000  <unknown>", Unwinder::FormatFrame(frame, true));
  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.
// Verify format frame code.
TEST_F(UnwinderTest, format_frame) {
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));
    ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 10));


  regs_.FakeSetPc(0x2300);
    Unwinder unwinder(64, &maps_, regs, process_memory_);
  regs_.FakeSetSp(0x10000);

  Unwinder unwinder(64, &maps_, &regs_, process_memory_);
    unwinder.Unwind();
    unwinder.Unwind();


    ASSERT_EQ(1U, unwinder.NumFrames());
    ASSERT_EQ(1U, unwinder.NumFrames());

    std::string expected;
  regs_.FakeSetArch(ARCH_ARM);
    switch (regs->Arch()) {
  EXPECT_EQ("  #00 pc 00001300  /system/fake/libc.so (Frame0+10)", unwinder.FormatFrame(0));
      case ARCH_ARM:
  regs_.FakeSetArch(ARCH_X86);
      case ARCH_X86:
  EXPECT_EQ("  #00 pc 00001300  /system/fake/libc.so (Frame0+10)", unwinder.FormatFrame(0));
        expected = "  #00 pc 00001300  /system/fake/libc.so (Frame0+10)";

        break;
  regs_.FakeSetArch(ARCH_ARM64);
      case ARCH_ARM64:
  EXPECT_EQ("  #00 pc 0000000000001300  /system/fake/libc.so (Frame0+10)", unwinder.FormatFrame(0));
      case ARCH_X86_64:
  regs_.FakeSetArch(ARCH_X86_64);
        expected = "  #00 pc 0000000000001300  /system/fake/libc.so (Frame0+10)";
  EXPECT_EQ("  #00 pc 0000000000001300  /system/fake/libc.so (Frame0+10)", unwinder.FormatFrame(0));
        break;

      default:
  EXPECT_EQ("", unwinder.FormatFrame(1));
        expected = "";
    }
    EXPECT_EQ(expected, unwinder.FormatFrame(0))
        << "Mismatch of frame format for regs arch " << ArchToString(regs->Arch());
    delete regs;
  }
}
}


}  // namespace unwindstack
}  // namespace unwindstack