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

Commit b99ec545 authored by Christopher Ferris's avatar Christopher Ferris Committed by android-build-merger
Browse files

Merge "Do not remove speculative frames in all cases."

am: 0d7c0f78

Change-Id: Id4e5c240cb9c8d98f428a4a38764a65379d2dabb
parents ee6c1be9 0d7c0f78
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -239,8 +239,14 @@ void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip,

    if (!stepped) {
      if (return_address_attempt) {
        // Only remove the speculative frame if there are more than two frames
        // or the pc in the first frame is in a valid map.
        // This allows for a case where the code jumps into the middle of
        // nowhere, but there is no other unwind information after that.
        if (frames_.size() != 2 || maps_->Find(frames_[0].pc) != nullptr) {
          // Remove the speculative frame.
          frames_.pop_back();
        }
        break;
      } else if (in_device_map) {
        // Do not attempt any other unwinding, pc or sp is in a device
+63 −1
Original line number Diff line number Diff line
@@ -659,6 +659,54 @@ TEST_F(UnwinderTest, speculative_frame_removed) {
  ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
  ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));

  // Fake as if code called a nullptr function.
  regs_.set_pc(0x20000);
  regs_.set_sp(0x10000);
  ElfInterfaceFake::FakePushStepData(StepData(0, 0x10010, false));
  regs_.FakeSetReturnAddress(0x12);
  regs_.FakeSetReturnAddressValid(true);

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

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

  auto* frame = &unwinder.frames()[0];
  EXPECT_EQ(0U, frame->num);
  EXPECT_EQ(0U, frame->rel_pc);
  EXPECT_EQ(0x20000U, frame->pc);
  EXPECT_EQ(0x10000U, frame->sp);
  EXPECT_EQ("Frame0", frame->function_name);
  EXPECT_EQ(0U, frame->function_offset);
  EXPECT_EQ("/system/fake/libunwind.so", frame->map_name);
  EXPECT_EQ(0U, frame->map_offset);
  EXPECT_EQ(0x20000U, frame->map_start);
  EXPECT_EQ(0x22000U, 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(0U, frame->rel_pc);
  EXPECT_EQ(0U, frame->pc);
  EXPECT_EQ(0x10010U, 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);
}

// Verify that a speculative frame is added and left if there are only
// two frames and the pc is in the middle nowhere.
TEST_F(UnwinderTest, speculative_frame_not_removed_pc_bad) {
  ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
  ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));

  // Fake as if code called a nullptr function.
  regs_.set_pc(0);
  regs_.set_sp(0x10000);
@@ -669,7 +717,7 @@ TEST_F(UnwinderTest, speculative_frame_removed) {
  unwinder.Unwind();
  EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());

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

  auto* frame = &unwinder.frames()[0];
  EXPECT_EQ(0U, frame->num);
@@ -684,6 +732,20 @@ TEST_F(UnwinderTest, speculative_frame_removed) {
  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(0x200U, frame->rel_pc);
  EXPECT_EQ(0x1200U, 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 that an unwind stops when a frame is in given suffix.