[svsm-devel] [PR] elf: Add unit tests
Carlos Bilbao
carlos.bilbao at amd.com
Mon Sep 18 17:33:04 CEST 2023
Hello,
Just opened pull request to add unit tests for ELF handling [1]. Sharing
patch below too in case anyone wants to review.
[1] https://github.com/coconut-svsm/svsm/pull/99
Thanks,
Carlos
---
Subject: [PATCH] elf: Add unit tests
Add unit tests to test correct behavior of ELF handling.
Signed-off-by: Carlos Bilbao <carlos.bilbao at amd.com>
---
src/elf/mod.rs | 195 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 195 insertions(+)
diff --git a/src/elf/mod.rs b/src/elf/mod.rs
index 39731f8..891c462 100644
--- a/src/elf/mod.rs
+++ b/src/elf/mod.rs
@@ -1605,3 +1605,198 @@ impl<'a, RP: Elf64RelocProcessor> Iterator for
Elf64AppliedRelaIterator<'a, RP>
Some(Ok(Some(reloc_op)))
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_elf64_shdr_verify_methods() {
+ // Create a valid Elf64Shdr instance for testing.
+ let valid_shdr = Elf64Shdr {
+ sh_name: 1,
+ sh_type: 2,
+ sh_flags: Elf64ShdrFlags::WRITE | Elf64ShdrFlags::ALLOC,
+ sh_addr: 0x1000,
+ sh_offset: 0x2000,
+ sh_size: 0x3000,
+ sh_link: 3,
+ sh_info: 4,
+ sh_addralign: 8,
+ sh_entsize: 0,
+ };
+
+ // Verify that the valid Elf64Shdr instance passes verification.
+ assert!(valid_shdr.verify().is_ok());
+
+ // Create an invalid Elf64Shdr instance for testing.
+ let invalid_shdr = Elf64Shdr {
+ sh_name: 0,
+ sh_type: 2,
+ sh_flags: Elf64ShdrFlags::from_bits(0).unwrap(),
+ sh_addr: 0x1000,
+ sh_offset: 0x2000,
+ sh_size: 0x3000,
+ sh_link: 3,
+ sh_info: 4,
+ sh_addralign: 7, // Invalid alignment
+ sh_entsize: 0,
+ };
+
+ // Verify that the invalid Elf64Shdr instance fails verification.
+ assert!(invalid_shdr.verify().is_err());
+ }
+
+ #[test]
+ fn test_elf64_dynamic_reloc_table_verify_valid() {
+ // Create a valid Elf64DynamicRelocTable instance for testing.
+ let reloc_table = Elf64DynamicRelocTable {
+ base_vaddr: 0x1000,
+ size: 0x2000,
+ entsize: 0x30,
+ };
+
+ // Verify that the valid Elf64DynamicRelocTable instance passes
verification.
+ assert!(reloc_table.verify().is_ok());
+ }
+
+ #[test]
+ fn test_elf64_addr_range_methods() {
+ // Test Elf64AddrRange::len() and Elf64AddrRange::is_empty().
+
+ // Create an Elf64AddrRange instance for testing.
+ let addr_range = Elf64AddrRange {
+ vaddr_begin: 0x1000,
+ vaddr_end: 0x2000,
+ };
+
+ // Check that the length calculation is correct.
+ assert_eq!(addr_range.len(), 0x1000);
+
+ // Check if the address range is empty.
+ assert!(!addr_range.is_empty());
+
+ // Test Elf64AddrRange::try_from().
+
+ // Create a valid input tuple for try_from.
+ let valid_input: (Elf64Addr, Elf64Xword) = (0x1000, 0x2000);
+
+ // Attempt to create an Elf64AddrRange from the valid input.
+ let result = Elf64AddrRange::try_from(valid_input);
+
+ // Verify that the result is Ok and contains the expected
Elf64AddrRange.
+ assert!(result.is_ok());
+ let valid_addr_range = result.unwrap();
+ assert_eq!(valid_addr_range.vaddr_begin, 0x1000);
+ assert_eq!(valid_addr_range.vaddr_end, 0x3000);
+ }
+
+ #[test]
+ fn test_elf64_file_range_try_from() {
+ // Valid range
+ let valid_range: (Elf64Off, Elf64Xword) = (0, 100);
+ let result: Result<Elf64FileRange, ElfError> = valid_range.try_into();
+ assert!(result.is_ok());
+ let file_range = result.unwrap();
+ assert_eq!(file_range.offset_begin, 0);
+ assert_eq!(file_range.offset_end, 100);
+
+ // Invalid range (overflow)
+ let invalid_range: (Elf64Off, Elf64Xword) = (usize::MAX as
Elf64Off, 100);
+ let result: Result<Elf64FileRange, ElfError> =
invalid_range.try_into();
+ assert!(result.is_err());
+ }
+
+ #[test]
+ fn test_elf64_file_read() {
+ // In the future, you can play around with this skeleton ELF
+ // file to test other cases
+ let byte_data: [u8; 184] = [
+ // ELF Header
+ 0x7F, 0x45, 0x4C, 0x46, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x3E, 0x00, 0x01, 0x00, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, // Program Header (with PT_LOAD)
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, // Section Header (simplified)
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, // Raw Machine Code Instructions
+ 0xf3, 0x0f, 0x1e, 0xfa, 0x31, 0xed, 0x49, 0x89, 0xd1, 0x5e,
0x48, 0x89, 0xe2, 0x48,
+ 0x83, 0xe4, 0xf0, 0x50, 0x54, 0x45, 0x31, 0xc0, 0x31, 0xc9,
0x48, 0x8d, 0x3d, 0xca,
+ 0x00, 0x00, 0x00, 0xff, 0x15, 0x53, 0x2f, 0x00, 0x00, 0xf4,
0x66, 0x2e, 0x0f, 0x1f,
+ 0x84, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x3d, 0x79, 0x2f,
0x00, 0x00, 0x48, 0x8d,
+ 0x05, 0x72, 0x2f, 0x00, 0x00, 0x48, 0x39, 0xf8, 0x74, 0x15,
0x48, 0x8b, 0x05, 0x36,
+ 0x2f, 0x00, 0x00, 0x48, 0x85, 0xc0, 0x74, 0x09, 0xff, 0xe0,
0x0f, 0x1f, 0x80, 0x00,
+ 0x00, 0x00, 0x00, 0xc3,
+ ];
+
+ // Use the Elf64File::read method to create an Elf64File instance
+ match Elf64File::read(&byte_data) {
+ Ok(_elf_file) => {
+ assert!(false);
+ }
+ Err(err) => {
+ assert!(matches!(err, crate::elf::ElfError::InvalidPhdrSize));
+ }
+ }
+
+ // Construct an Elf64Hdr instance from the byte data
+ let elf_hdr = Elf64Hdr::read(&byte_data).expect("Failed to read
ELF header");
+ let expected_type = 2;
+ let expected_machine = 0x3E;
+ let expected_version = 1;
+
+ // Assert that the fields of the header match the expected values
+ assert_eq!(elf_hdr.e_type, expected_type);
+ assert_eq!(elf_hdr.e_machine, expected_machine);
+ assert_eq!(elf_hdr.e_version, expected_version);
+ }
+
+ #[test]
+ fn test_elf64_load_segments() {
+ let mut load_segments = Elf64LoadSegments::new();
+ let vaddr_range1 = Elf64AddrRange {
+ vaddr_begin: 0x1000,
+ vaddr_end: 0x2000,
+ };
+ let vaddr_range2 = Elf64AddrRange {
+ vaddr_begin: 0x3000,
+ vaddr_end: 0x4000,
+ };
+ let segment_index1 = 0;
+ let segment_index2 = 1;
+
+ // Insert load segments
+ assert!(load_segments
+ .try_insert(vaddr_range1, segment_index1)
+ .is_ok());
+ assert!(load_segments
+ .try_insert(vaddr_range2, segment_index2)
+ .is_ok());
+
+ // Lookup load segments by virtual address
+ let (index1, offset1) = load_segments
+ .lookup_vaddr_range(&Elf64AddrRange {
+ vaddr_begin: 0x1500,
+ vaddr_end: 0x1700,
+ })
+ .unwrap();
+ let (index2, offset2) = load_segments
+ .lookup_vaddr_range(&Elf64AddrRange {
+ vaddr_begin: 0x3500,
+ vaddr_end: 0x3700,
+ })
+ .unwrap();
+
+ assert_eq!(index1, segment_index1);
+ assert_eq!(offset1, 0x500); // Offset within the segment
+ assert_eq!(index2, segment_index2);
+ assert_eq!(offset2, 0x500); // Offset within the segment
+
+ // Total virtual address range
+ let total_range = load_segments.total_vaddr_range();
+ assert_eq!(total_range.vaddr_begin, 0x1000);
+ assert_eq!(total_range.vaddr_end, 0x4000);
+ }
+}
--
2.41.0
More information about the Svsm-devel
mailing list