Merge "Don't hide error by INVALID_MAP in speculative frame."
diff --git a/libunwindstack/MapInfo.cpp b/libunwindstack/MapInfo.cpp
index 6193015..f19c6b7 100644
--- a/libunwindstack/MapInfo.cpp
+++ b/libunwindstack/MapInfo.cpp
@@ -120,7 +120,11 @@
   // and reinit to that size. This is needed because the dynamic linker
   // only maps in a portion of the original elf, and never the symbol
   // file data.
-  uint64_t map_size = end() - start();
+  //
+  // For maps with MAPS_FLAGS_JIT_SYMFILE_MAP, the map range is for a JIT function,
+  // which can be smaller than elf header size. So make sure map_size is large enough
+  // to read elf header.
+  uint64_t map_size = std::max<uint64_t>(end() - start(), sizeof(ElfTypes64::Ehdr));
   if (!memory->Init(name(), offset(), map_size)) {
     return nullptr;
   }
diff --git a/libunwindstack/tests/MapInfoGetElfTest.cpp b/libunwindstack/tests/MapInfoGetElfTest.cpp
index e7ebee5..79f470f 100644
--- a/libunwindstack/tests/MapInfoGetElfTest.cpp
+++ b/libunwindstack/tests/MapInfoGetElfTest.cpp
@@ -291,6 +291,37 @@
   ASSERT_TRUE(elf->memory()->ReadFully(0x1000, buffer.data(), 1));
 }
 
+// Verify that if the offset is non-zero and there is an elf at that
+// offset, that only part of the file is used. Further verify that if the
+// the initial map is smaller than elf header size, we can still read the elf.
+TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf64_small_map_range) {
+  auto info = MapInfo::Create(0x7000, 0x7004, 0x1000, PROT_READ, elf_.path);
+
+  std::vector<uint8_t> buffer(0x4000);
+  memset(buffer.data(), 0, buffer.size());
+  Elf64_Ehdr ehdr;
+  TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
+  ehdr.e_shoff = 0x2000;
+  ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
+  ehdr.e_shnum = 4;
+  memcpy(&buffer[info->offset()], &ehdr, sizeof(ehdr));
+  ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
+
+  Elf* elf = info->GetElf(process_memory_, ARCH_ARM64);
+  ASSERT_TRUE(elf != nullptr);
+  ASSERT_TRUE(elf->valid());
+  ASSERT_TRUE(elf->memory() != nullptr);
+  ASSERT_EQ(0U, info->elf_offset());
+
+  // Verify the memory is a valid elf.
+  memset(buffer.data(), 0, buffer.size());
+  ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), 0x1000));
+  ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
+
+  // Read past the end of what would normally be the size of the map.
+  ASSERT_TRUE(elf->memory()->ReadFully(0x1000, buffer.data(), 1));
+}
+
 TEST_F(MapInfoGetElfTest, check_device_maps) {
   // Create valid elf data in process memory for this to verify that only
   // the name is causing invalid elf data.