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

Commit 3ff3ff1c authored by Christopher Ferris's avatar Christopher Ferris Committed by Gerrit Code Review
Browse files

Merge "Check that dex pc is in a valid map."

parents 28c44863 e762f1f1
Loading
Loading
Loading
Loading
+12 −7
Original line number Diff line number Diff line
@@ -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;
@@ -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) {
+6 −6
Original line number Diff line number Diff line
@@ -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 {
+1 −0
Original line number Diff line number Diff line
@@ -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; }

+86 −0
Original line number Diff line number Diff line
@@ -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);
  }

@@ -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_, &regs_, 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_, &regs_, 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;