use super::*; fn minimal_elf64() -> [u8; 120] { let mut buf = [0u8; 120]; // ELF magic buf[0] = 0x7f; buf[1] = b'E'; buf[2] = b'L'; buf[3] = b'F'; // EI_CLASS = ELFCLASS64 buf[4] = 2; // EI_DATA = ELFDATA2LSB buf[5] = 1; // EI_VERSION buf[6] = 1; // e_type = ET_EXEC (2) buf[16] = 2; buf[17] = 0; // e_entry = 0x1000 let entry: u64 = 0x1000; buf[24..32].copy_from_slice(&entry.to_le_bytes()); // e_phoff = 64 (right after ELF header) let phoff: u64 = 64; buf[32..40].copy_from_slice(&phoff.to_le_bytes()); // e_phentsize = 56 buf[54] = 56; buf[55] = 0; // e_phnum = 1 buf[56] = 1; buf[57] = 0; // Program header at offset 64: let ph = 64; // p_type = PT_LOAD (1) buf[ph] = 1; // p_flags = PF_R | PF_X (4 | 1 = 5) buf[ph + 4] = 5; // p_offset = 0 let p_offset: u64 = 0; buf[ph + 8..ph + 16].copy_from_slice(&p_offset.to_le_bytes()); // p_vaddr = 0x1000 let p_vaddr: u64 = 0x1000; buf[ph + 16..ph + 24].copy_from_slice(&p_vaddr.to_le_bytes()); // p_filesz = 120 let p_filesz: u64 = 120; buf[ph + 32..ph + 40].copy_from_slice(&p_filesz.to_le_bytes()); // p_memsz = 4096 let p_memsz: u64 = 4096; buf[ph + 40..ph + 48].copy_from_slice(&p_memsz.to_le_bytes()); buf } #[test] fn parse_valid_elf64() { let data = minimal_elf64(); let info = parse(&data).unwrap(); assert_eq!(info.entry_point, 0x1000); assert_eq!(info.segment_count, 1); let seg = info.segments().next().unwrap(); assert_eq!(seg.vaddr, 0x1000); assert_eq!(seg.file_size, 120); assert_eq!(seg.mem_size, 4096); assert!(seg.flags.read); assert!(seg.flags.execute); assert!(!seg.flags.write); } #[test] fn parse_too_small_fails() { let data = [0u8; 10]; assert_eq!(parse(&data), Err(ElfError::TooSmall)); } #[test] fn parse_bad_magic_fails() { let mut data = minimal_elf64(); data[0] = 0; assert_eq!(parse(&data), Err(ElfError::InvalidMagic)); } #[test] fn parse_32bit_fails() { let mut data = minimal_elf64(); data[4] = 1; // ELFCLASS32 assert_eq!(parse(&data), Err(ElfError::Not64Bit)); } #[test] fn parse_big_endian_fails() { let mut data = minimal_elf64(); data[5] = 2; // ELFDATA2MSB assert_eq!(parse(&data), Err(ElfError::NotLittleEndian)); } #[test] fn parse_shared_object_fails() { let mut data = minimal_elf64(); data[16] = 3; // ET_DYN assert_eq!(parse(&data), Err(ElfError::NotExecutable)); } #[test] fn total_pages_rounds_up() { let data = minimal_elf64(); let info = parse(&data).unwrap(); assert_eq!(info.total_pages(), 1); } #[test] fn skips_non_load_segments() { let mut data = minimal_elf64(); // Change p_type to PT_NOTE (4) data[64] = 4; let info = parse(&data).unwrap(); assert_eq!(info.segment_count, 0); }