From 93dbe98441163ded01f6ff2a6561fc5f5cbd6e15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=BCller?= Date: Wed, 30 Oct 2024 13:13:30 -0700 Subject: [PATCH] Add regression test for #875 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a regression test for the change introduced with pull request #875. It's unfortunately very involved and cumbersome to come up with a complete end-to-end test and so with this change we add a unit test based on partial data from the binary in question. Signed-off-by: Daniel Müller --- src/elf/parser.rs | 75 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/src/elf/parser.rs b/src/elf/parser.rs index afd7331c..ba7f56eb 100644 --- a/src/elf/parser.rs +++ b/src/elf/parser.rs @@ -1171,6 +1171,81 @@ mod tests { test(&so); } + /// Check that we can correctly convert a file offset into a virtual + /// offset. + /// + /// This is a regression test for the case that a program header + /// with a memory size greater than file size is located before a + /// program header that would otherwise match the file offset. Refer + /// to commit 1a4e10740652 ("Use file size in file offset -> virtual + /// offset translation"). + #[test] + fn virtual_offset_calculation() { + #[repr(C)] + struct Elf { + ehdr: Elf64_Ehdr, + phdrs: [Elf64_Phdr; 2], + } + + // Data is mostly made up, except for relevant program headers, + // which were copied from a real binary. + let elf = Elf { + ehdr: Elf64_Ehdr { + e_ident: [127, 69, 76, 70, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], + e_type: 3, + e_machine: 62, + e_version: 1, + e_entry: 4208, + e_phoff: size_of::() as _, + e_shoff: 0, + e_flags: 0, + e_ehsize: 64, + e_phentsize: 56, + e_phnum: 2, + e_shentsize: 0, + e_shnum: 1, + e_shstrndx: 0, + }, + phdrs: [ + Elf64_Phdr { + p_type: 1, + p_flags: 6, + p_offset: 455231872, + p_vaddr: 457337216, + p_paddr: 457337216, + p_filesz: 3422344, + p_memsz: 13261132, + p_align: 4096, + }, + Elf64_Phdr { + p_type: 1, + p_flags: 5, + p_offset: 459276288, + p_vaddr: 471859200, + p_paddr: 471859200, + p_filesz: 77813932, + p_memsz: 77813932, + p_align: 2097152, + }, + ], + }; + + let mut file = NamedTempFile::new().unwrap(); + let dump = + unsafe { slice::from_raw_parts((&elf as *const Elf).cast::(), size_of::()) }; + let () = file.write_all(dump).unwrap(); + let () = file.rewind().unwrap(); + + let parser = ElfParser::open_file(file.as_file(), file.path()).unwrap(); + // A file offset as produced by normalization. + let file_offset = 0x1b63b4d0; + let virt_offset = parser + .file_offset_to_virt_offset(file_offset) + .unwrap() + .unwrap(); + assert_eq!(virt_offset, 0x1c23b4d0); + } + /// Make sure that we can look up a symbol in an ELF file. #[test] fn lookup_symbol() {