Merge "Don't hide error by INVALID_MAP in speculative frame."
diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp
index 0536f6d..2312652 100644
--- a/libunwindstack/Unwinder.cpp
+++ b/libunwindstack/Unwinder.cpp
@@ -150,7 +150,11 @@
     if (map_info == nullptr) {
       step_pc = regs_->pc();
       rel_pc = step_pc;
-      last_error_.code = ERROR_INVALID_MAP;
+      // If we get invalid map via return_address_attempt, don't hide error for the previous frame.
+      if (!return_address_attempt || last_error_.code == ERROR_NONE) {
+        last_error_.code = ERROR_INVALID_MAP;
+        last_error_.address = step_pc;
+      }
       elf = nullptr;
     } else {
       if (ShouldStop(map_suffixes_to_ignore, map_info->name())) {
diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp
index b37f9d1..8e43fe4 100644
--- a/libunwindstack/tests/UnwinderTest.cpp
+++ b/libunwindstack/tests/UnwinderTest.cpp
@@ -887,6 +887,32 @@
   ASSERT_EQ(0U, unwinder.NumFrames());
 }
 
+// Verify that a speculative frame mapping to invalid map doesn't hide error
+// for the previous frame.
+TEST_F(UnwinderTest, speculative_frame_to_invalid_map_not_hide_prev_error) {
+  regs_.set_pc(0x100000);
+  regs_.set_sp(0x10000);
+  regs_.FakeSetReturnAddress(0x4);
+  regs_.FakeSetReturnAddressValid(true);
+
+  Unwinder unwinder(64, maps_.get(), &regs_, process_memory_);
+  unwinder.Unwind();
+  EXPECT_EQ(ERROR_INVALID_ELF, unwinder.LastErrorCode());
+  EXPECT_EQ(WARNING_NONE, unwinder.warnings());
+  EXPECT_FALSE(unwinder.elf_from_memory_not_file());
+
+  ASSERT_EQ(1U, unwinder.NumFrames());
+
+  auto* frame = &unwinder.frames()[0];
+  EXPECT_EQ(0U, frame->num);
+  EXPECT_EQ(0x300U, frame->rel_pc);
+  EXPECT_EQ(0x100000U, frame->pc);
+  EXPECT_EQ(0x10000U, frame->sp);
+  EXPECT_EQ("", frame->function_name);
+  EXPECT_EQ(0U, frame->function_offset);
+  ASSERT_TRUE(frame->map_info != nullptr);
+}
+
 // Verify that an unwind stops when a frame is in given suffix.
 TEST_F(UnwinderTest, map_ignore_suffixes) {
   ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));