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.