diff options
Diffstat (limited to 'libunwindstack/tests/MapInfoCreateMemoryTest.cpp')
-rw-r--r-- | libunwindstack/tests/MapInfoCreateMemoryTest.cpp | 84 |
1 files changed, 71 insertions, 13 deletions
diff --git a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp index 9e45e7812..2aab9c652 100644 --- a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp +++ b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp @@ -38,30 +38,50 @@ namespace unwindstack { class MapInfoCreateMemoryTest : public ::testing::Test { protected: + template <typename Ehdr, typename Shdr> + static void InitElf(int fd, uint64_t file_offset, uint64_t sh_offset, uint8_t class_type) { + std::vector<uint8_t> buffer(20000); + memset(buffer.data(), 0, buffer.size()); + + Ehdr ehdr; + memset(&ehdr, 0, sizeof(ehdr)); + memcpy(ehdr.e_ident, ELFMAG, SELFMAG); + ehdr.e_ident[EI_CLASS] = class_type; + ehdr.e_shoff = sh_offset; + ehdr.e_shentsize = sizeof(Shdr) + 100; + ehdr.e_shnum = 4; + memcpy(&buffer[file_offset], &ehdr, sizeof(ehdr)); + + ASSERT_TRUE(android::base::WriteFully(fd, buffer.data(), buffer.size())); + } + static void SetUpTestCase() { std::vector<uint8_t> buffer(1024); + memset(buffer.data(), 0, buffer.size()); memcpy(buffer.data(), ELFMAG, SELFMAG); - for (size_t i = SELFMAG; i < buffer.size(); i++) { - buffer[i] = i / 256 + 1; - } + buffer[EI_CLASS] = ELFCLASS32; ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size())); - for (size_t i = 0; i < 0x100; i++) { - buffer[i] = i / 256 + 1; - } + memset(buffer.data(), 0, buffer.size()); memcpy(&buffer[0x100], ELFMAG, SELFMAG); - for (size_t i = 0x100 + SELFMAG; i < buffer.size(); i++) { - buffer[i] = i / 256 + 1; - } + buffer[0x100 + EI_CLASS] = ELFCLASS64; ASSERT_TRUE(android::base::WriteFully(elf_at_100_.fd, buffer.data(), buffer.size())); + + InitElf<Elf32_Ehdr, Elf32_Shdr>(elf32_at_map_.fd, 0x1000, 0x2000, ELFCLASS32); + InitElf<Elf64_Ehdr, Elf64_Shdr>(elf64_at_map_.fd, 0x2000, 0x3000, ELFCLASS64); } static TemporaryFile elf_; static TemporaryFile elf_at_100_; + + static TemporaryFile elf32_at_map_; + static TemporaryFile elf64_at_map_; }; TemporaryFile MapInfoCreateMemoryTest::elf_; TemporaryFile MapInfoCreateMemoryTest::elf_at_100_; +TemporaryFile MapInfoCreateMemoryTest::elf32_at_map_; +TemporaryFile MapInfoCreateMemoryTest::elf64_at_map_; TEST_F(MapInfoCreateMemoryTest, end_le_start) { MapInfo info{.start = 0x100, .end = 0x100, .offset = 0, .name = elf_.path}; @@ -93,8 +113,9 @@ TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_full_file) { std::vector<uint8_t> buffer(1024); ASSERT_TRUE(memory->Read(0, buffer.data(), 1024)); ASSERT_TRUE(memcmp(buffer.data(), ELFMAG, SELFMAG) == 0); - for (size_t i = SELFMAG; i < buffer.size(); i++) { - ASSERT_EQ(i / 256 + 1, buffer[i]) << "Failed at byte " << i; + ASSERT_EQ(ELFCLASS32, buffer[EI_CLASS]); + for (size_t i = EI_CLASS + 1; i < buffer.size(); i++) { + ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i; } ASSERT_FALSE(memory->Read(1024, buffer.data(), 1)); @@ -113,13 +134,50 @@ TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file) { std::vector<uint8_t> buffer(0x100); ASSERT_TRUE(memory->Read(0, buffer.data(), 0x100)); ASSERT_TRUE(memcmp(buffer.data(), ELFMAG, SELFMAG) == 0); - for (size_t i = SELFMAG; i < buffer.size(); i++) { - ASSERT_EQ(2, buffer[i]) << "Failed at byte " << i; + ASSERT_EQ(ELFCLASS64, buffer[EI_CLASS]); + for (size_t i = EI_CLASS + 1; i < buffer.size(); i++) { + ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i; } ASSERT_FALSE(memory->Read(0x100, 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 +// embedded elf is bigger than the initial map, the new object is larger +// than the original map size. Do this for a 32 bit elf and a 64 bit elf. +TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_elf32) { + MapInfo info{.start = 0x5000, .end = 0x6000, .offset = 0x1000, .name = elf32_at_map_.path}; + + std::unique_ptr<Memory> memory(info.CreateMemory(getpid())); + ASSERT_TRUE(memory.get() != nullptr); + ASSERT_EQ(0U, info.elf_offset); + + // Verify the memory is a valid elf. + uint8_t e_ident[SELFMAG + 1]; + ASSERT_TRUE(memory->Read(0, e_ident, SELFMAG)); + ASSERT_EQ(0, memcmp(e_ident, ELFMAG, SELFMAG)); + + // Read past the end of what would normally be the size of the map. + ASSERT_TRUE(memory->Read(0x1000, e_ident, 1)); +} + +TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_elf64) { + MapInfo info{.start = 0x7000, .end = 0x8000, .offset = 0x2000, .name = elf64_at_map_.path}; + + std::unique_ptr<Memory> memory(info.CreateMemory(getpid())); + ASSERT_TRUE(memory.get() != nullptr); + ASSERT_EQ(0U, info.elf_offset); + + // Verify the memory is a valid elf. + uint8_t e_ident[SELFMAG + 1]; + ASSERT_TRUE(memory->Read(0, e_ident, SELFMAG)); + ASSERT_EQ(0, memcmp(e_ident, ELFMAG, SELFMAG)); + + // Read past the end of what would normally be the size of the map. + ASSERT_TRUE(memory->Read(0x1000, e_ident, 1)); +} + // Verify that device file names will never result in Memory object creation. TEST_F(MapInfoCreateMemoryTest, check_device_maps) { // Set up some memory so that a valid local memory object would |