From eef7346fb2231f8741410381198015cceeebfac9 Mon Sep 17 00:00:00 2001 From: Billy McFall <22157057+Billy99@users.noreply.github.com> Date: Thu, 27 Jun 2024 12:44:22 -0400 Subject: [PATCH 1/4] test: adjust test byte arrays for big endian Adding support for s390x (big endian architecture) and found that some of the unit tests have structures and files implemented as byte arrays. They are all coded as little endian and need a bug endian version to work properly. Signed-off-by: Billy McFall <22157057+Billy99@users.noreply.github.com> --- aya-log/src/lib.rs | 5 ++ aya-obj/src/btf/btf.rs | 71 +++++++++++++++++++ aya-obj/src/btf/types.rs | 116 +++++++++++++++++++++++++++++++ aya-obj/src/obj.rs | 98 ++++++++++++++++++++++++++ aya/src/maps/perf/perf_buffer.rs | 19 ++++- 5 files changed, 307 insertions(+), 2 deletions(-) diff --git a/aya-log/src/lib.rs b/aya-log/src/lib.rs index 307d12f2..9dcbb2f5 100644 --- a/aya-log/src/lib.rs +++ b/aya-log/src/lib.rs @@ -997,9 +997,14 @@ mod test { len += "ipv6: ".write(&mut input[len..]).unwrap().get(); len += DisplayHint::Ip.write(&mut input[len..]).unwrap().get(); // 2001:db8::1:1 as u16 array + #[cfg(target_endian = "little")] let ipv6_arr: [u16; 8] = [ 0x2001, 0x0db8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, ]; + #[cfg(target_endian = "big")] + let ipv6_arr: [u16; 8] = [ + 0x0120, 0xb80d, 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, 0x0100, + ]; len += ipv6_arr.write(&mut input[len..]).unwrap().get(); _ = len; diff --git a/aya-obj/src/btf/btf.rs b/aya-obj/src/btf/btf.rs index ef7217ad..9fbdc496 100644 --- a/aya-obj/src/btf/btf.rs +++ b/aya-obj/src/btf/btf.rs @@ -1110,10 +1110,16 @@ mod tests { #[test] fn test_parse_header() { + #[cfg(target_endian = "little")] let data: &[u8] = &[ 0x9f, 0xeb, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x54, 0x2a, 0x00, 0x64, 0x54, 0x2a, 0x00, 0x10, 0x64, 0x1c, 0x00, ]; + #[cfg(target_endian = "big")] + let data: &[u8] = &[ + 0xeb, 0x9f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, + 0x54, 0x64, 0x00, 0x2a, 0x54, 0x64, 0x00, 0x1c, 0x64, 0x10, + ]; let header = unsafe { read_btf_header(data) }; assert_eq!(header.magic, 0xeb9f); assert_eq!(header.version, 0x01); @@ -1129,6 +1135,7 @@ mod tests { fn test_parse_btf() { // this generated BTF data is from an XDP program that simply returns XDP_PASS // compiled using clang + #[cfg(target_endian = "little")] let data: &[u8] = &[ 0x9f, 0xeb, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x0c, 0x01, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -1168,12 +1175,53 @@ mod tests { 0x5a, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x5f, 0x00, 0x5f, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x00, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x00, ]; + #[cfg(target_endian = "big")] + let data: &[u8] = &[ + 0xeb, 0x9f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x0c, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x3f, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x4e, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x54, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x65, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x69, 0x0c, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x00, 0xb7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0xbc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0xd0, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0xd9, 0x0f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x78, + 0x64, 0x70, 0x5f, 0x6d, 0x64, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x64, 0x61, 0x74, + 0x61, 0x5f, 0x65, 0x6e, 0x64, 0x00, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6d, 0x65, 0x74, + 0x61, 0x00, 0x69, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x69, 0x66, 0x69, 0x6e, + 0x64, 0x65, 0x78, 0x00, 0x72, 0x78, 0x5f, 0x71, 0x75, 0x65, 0x75, 0x65, 0x5f, 0x69, + 0x6e, 0x64, 0x65, 0x78, 0x00, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x69, 0x66, + 0x69, 0x6e, 0x64, 0x65, 0x78, 0x00, 0x5f, 0x5f, 0x75, 0x33, 0x32, 0x00, 0x75, 0x6e, + 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x00, 0x63, 0x74, 0x78, + 0x00, 0x69, 0x6e, 0x74, 0x00, 0x78, 0x64, 0x70, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x00, + 0x78, 0x64, 0x70, 0x2f, 0x70, 0x61, 0x73, 0x73, 0x00, 0x2f, 0x68, 0x6f, 0x6d, 0x65, + 0x2f, 0x64, 0x61, 0x76, 0x65, 0x2f, 0x64, 0x65, 0x76, 0x2f, 0x62, 0x70, 0x66, 0x64, + 0x2f, 0x62, 0x70, 0x66, 0x2f, 0x78, 0x64, 0x70, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x2e, + 0x62, 0x70, 0x66, 0x2e, 0x63, 0x00, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x58, 0x44, 0x50, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x3b, 0x00, 0x63, + 0x68, 0x61, 0x72, 0x00, 0x5f, 0x5f, 0x41, 0x52, 0x52, 0x41, 0x59, 0x5f, 0x53, 0x49, + 0x5a, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x5f, 0x00, 0x5f, 0x6c, 0x69, 0x63, + 0x65, 0x6e, 0x73, 0x65, 0x00, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x00, + ]; assert_eq!(data.len(), 517); let btf = Btf::parse(data, Endianness::default()).unwrap_or_else(|e| panic!("{}", e)); let data2 = btf.to_bytes(); assert_eq!(data2.len(), 517); assert_eq!(data, data2); + #[cfg(target_endian = "little")] let ext_data: &[u8] = &[ 0x9f, 0xeb, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, @@ -1182,6 +1230,15 @@ mod tests { 0x72, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0x05, 0x2c, 0x00, 0x00, ]; + #[cfg(target_endian = "big")] + let ext_data: &[u8] = &[ + 0xeb, 0x9f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7b, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x2c, 0x05, + ]; assert_eq!(ext_data.len(), 80); let _: BtfExt = BtfExt::parse(ext_data, Endianness::default(), &btf) @@ -1190,13 +1247,26 @@ mod tests { #[test] fn parsing_older_ext_data() { + #[cfg(target_endian = "little")] let btf_data = [ 159, 235, 1, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, ]; + #[cfg(target_endian = "big")] + let btf_data = [ + 235, 159, 1, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + ]; + + #[cfg(target_endian = "little")] let btf_ext_data = [ 159, 235, 1, 0, 24, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 16, 0, 0, 0, ]; + #[cfg(target_endian = "big")] + let btf_ext_data = [ + 235, 159, 1, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 16, + ]; + let btf = Btf::parse(&btf_data, Endianness::default()).unwrap(); let btf_ext = BtfExt::parse(&btf_ext_data, Endianness::default(), &btf).unwrap(); assert_eq!(btf_ext.func_info_rec_size(), 8); @@ -1704,6 +1774,7 @@ mod tests { #[test] #[cfg(feature = "std")] #[cfg_attr(miri, ignore = "`open` not available when isolation is enabled")] + #[cfg(target_endian = "little")] fn test_read_btf_from_sys_fs() { let btf = Btf::parse_file("/sys/kernel/btf/vmlinux", Endianness::default()).unwrap(); let task_struct_id = btf diff --git a/aya-obj/src/btf/types.rs b/aya-obj/src/btf/types.rs index 89b1713b..a4190ea7 100644 --- a/aya-obj/src/btf/types.rs +++ b/aya-obj/src/btf/types.rs @@ -1577,10 +1577,16 @@ mod tests { #[test] fn test_read_btf_type_int() { let endianness = Endianness::default(); + #[cfg(target_endian = "little")] let data: &[u8] = &[ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, ]; + #[cfg(target_endian = "big")] + let data: &[u8] = &[ + 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x40, + ]; assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Int(new @ Int { name_offset, info: _, @@ -1596,30 +1602,48 @@ mod tests { #[test] fn test_write_btf_long_unsigned_int() { + #[cfg(target_endian = "little")] let data: &[u8] = &[ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, ]; + #[cfg(target_endian = "big")] + let data: &[u8] = &[ + 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x40, + ]; let int = Int::new(1, 8, IntEncoding::None, 0); assert_eq!(int.to_bytes(), data); } #[test] fn test_write_btf_uchar() { + #[cfg(target_endian = "little")] let data: &[u8] = &[ 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, ]; + #[cfg(target_endian = "big")] + let data: &[u8] = &[ + 0x00, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x08, + ]; let int = Int::new(0x13, 1, IntEncoding::None, 0); assert_eq!(int.to_bytes(), data); } #[test] fn test_write_btf_signed_short_int() { + #[cfg(target_endian = "little")] let data: &[u8] = &[ 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, ]; + #[cfg(target_endian = "big")] + let data: &[u8] = &[ + 0x00, 0x00, 0x00, 0x4a, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, + 0x00, 0x10, + ]; let int = Int::new(0x4a, 2, IntEncoding::Signed, 0); assert_eq!(int.to_bytes(), data); } @@ -1627,9 +1651,14 @@ mod tests { #[test] fn test_read_btf_type_ptr() { let endianness = Endianness::default(); + #[cfg(target_endian = "little")] let data: &[u8] = &[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x00, ]; + #[cfg(target_endian = "big")] + let data: &[u8] = &[ + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + ]; assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Ptr(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1638,10 +1667,16 @@ mod tests { #[test] fn test_read_btf_type_array() { let endianness = Endianness::default(); + #[cfg(target_endian = "little")] let data: &[u8] = &[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, ]; + #[cfg(target_endian = "big")] + let data: &[u8] = &[ + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x02, + ]; assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Array(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1650,10 +1685,16 @@ mod tests { #[test] fn test_read_btf_type_struct() { let endianness = Endianness::default(); + #[cfg(target_endian = "little")] let data: &[u8] = &[ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x47, 0x02, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]; + #[cfg(target_endian = "big")] + let data: &[u8] = &[ + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x02, 0x47, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, + ]; assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Struct(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1662,10 +1703,16 @@ mod tests { #[test] fn test_read_btf_type_union() { let endianness = Endianness::default(); + #[cfg(target_endian = "little")] let data: &[u8] = &[ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0x04, 0x00, 0x00, 0x00, 0x0d, 0x04, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]; + #[cfg(target_endian = "big")] + let data: &[u8] = &[ + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x04, 0x0d, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, + ]; assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Union(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1674,10 +1721,16 @@ mod tests { #[test] fn test_read_btf_type_enum() { let endianness = Endianness::default(); + #[cfg(target_endian = "little")] let data: &[u8] = &[ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x00, 0xc9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, ]; + #[cfg(target_endian = "big")] + let data: &[u8] = &[ + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0xc9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x01, + ]; assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Enum(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1686,9 +1739,14 @@ mod tests { #[test] fn test_read_btf_type_fwd() { let endianness = Endianness::default(); + #[cfg(target_endian = "little")] let data: &[u8] = &[ 0x0b, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, ]; + #[cfg(target_endian = "big")] + let data: &[u8] = &[ + 0x00, 0x00, 0x55, 0x0b, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Fwd(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1697,9 +1755,14 @@ mod tests { #[test] fn test_read_btf_type_typedef() { let endianness = Endianness::default(); + #[cfg(target_endian = "little")] let data: &[u8] = &[ 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0b, 0x00, 0x00, 0x00, ]; + #[cfg(target_endian = "big")] + let data: &[u8] = &[ + 0x00, 0x00, 0x00, 0x31, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, + ]; assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Typedef(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1708,9 +1771,14 @@ mod tests { #[test] fn test_read_btf_type_volatile() { let endianness = Endianness::default(); + #[cfg(target_endian = "little")] let data: &[u8] = &[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x24, 0x00, 0x00, 0x00, ]; + #[cfg(target_endian = "big")] + let data: &[u8] = &[ + 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, + ]; assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Volatile(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1719,9 +1787,14 @@ mod tests { #[test] fn test_read_btf_type_const() { let endianness = Endianness::default(); + #[cfg(target_endian = "little")] let data: &[u8] = &[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x00, ]; + #[cfg(target_endian = "big")] + let data: &[u8] = &[ + 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + ]; assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Const(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1730,9 +1803,14 @@ mod tests { #[test] fn test_read_btf_type_restrict() { let endianness = Endianness::default(); + #[cfg(target_endian = "little")] let data: &[u8] = &[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x04, 0x00, 0x00, 0x00, ]; + #[cfg(target_endian = "big")] + let data: &[u8] = &[ + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + ]; assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Restrict(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1741,9 +1819,14 @@ mod tests { #[test] fn test_read_btf_type_func() { let endianness = Endianness::default(); + #[cfg(target_endian = "little")] let data: &[u8] = &[ 0x17, 0x8b, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xf0, 0xe4, 0x00, 0x00, ]; + #[cfg(target_endian = "big")] + let data: &[u8] = &[ + 0x00, 0x0f, 0x8b, 0x17, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xf0, + ]; assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Func(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1752,10 +1835,16 @@ mod tests { #[test] fn test_read_btf_type_func_proto() { let endianness = Endianness::default(); + #[cfg(target_endian = "little")] let data: &[u8] = &[ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, ]; + #[cfg(target_endian = "big")] + let data: &[u8] = &[ + 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, + ]; assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::FuncProto(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1765,10 +1854,16 @@ mod tests { fn test_read_btf_type_func_var() { let endianness = Endianness::default(); // NOTE: There was no data in /sys/kernell/btf/vmlinux for this type + #[cfg(target_endian = "little")] let data: &[u8] = &[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]; + #[cfg(target_endian = "big")] + let data: &[u8] = &[ + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, + 0x00, 0x00, + ]; assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Var(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1777,10 +1872,16 @@ mod tests { #[test] fn test_read_btf_type_func_datasec() { let endianness = Endianness::default(); + #[cfg(target_endian = "little")] let data: &[u8] = &[ 0xd9, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, ]; + #[cfg(target_endian = "big")] + let data: &[u8] = &[ + 0x00, 0x00, 0x00, 0xd9, 0x0f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + ]; assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::DataSec(DataSec { name_offset: _, info: _, @@ -1802,9 +1903,14 @@ mod tests { #[test] fn test_read_btf_type_float() { let endianness = Endianness::default(); + #[cfg(target_endian = "little")] let data: &[u8] = &[ 0x78, 0xfd, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x00, ]; + #[cfg(target_endian = "big")] + let data: &[u8] = &[ + 0x00, 0x02, 0xfd, 0x78, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + ]; assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Float(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1856,6 +1962,7 @@ mod tests { #[test] pub fn test_read_btf_type_enum64() { let endianness = Endianness::default(); + #[cfg(target_endian = "little")] let data: &[u8] = &[ 0x00, 0x00, 0x00, 0x00, // name offset 0x01, 0x00, 0x00, 0x13, // info: vlen, type_kind @@ -1864,6 +1971,15 @@ mod tests { 0xbb, 0xbb, 0xbb, 0xbb, // enum variant low 0xaa, 0xaa, 0xaa, 0xaa, // enum variant high ]; + #[cfg(target_endian = "big")] + let data: &[u8] = &[ + 0x00, 0x00, 0x00, 0x00, // name offset + 0x13, 0x00, 0x00, 0x01, // info: vlen, type_kind + 0x00, 0x00, 0x00, 0x08, // size + 0x00, 0x00, 0x06, 0xd7, // enum variant name offset + 0xbb, 0xbb, 0xbb, 0xbb, // enum variant low + 0xaa, 0xaa, 0xaa, 0xaa, // enum variant high + ]; assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Enum64(got) => { assert_eq!(got.to_bytes(), data); diff --git a/aya-obj/src/obj.rs b/aya-obj/src/obj.rs index f6f4fc8b..4c172e8e 100644 --- a/aya-obj/src/obj.rs +++ b/aya-obj/src/obj.rs @@ -1594,6 +1594,7 @@ mod tests { #[test] fn sanitizes_empty_btf_files_to_none() { let mut obj = fake_obj(); + #[cfg(target_endian = "little")] obj.parse_section(fake_section( EbpfSectionKind::Btf, ".BTF", @@ -1603,6 +1604,18 @@ mod tests { None, )) .unwrap(); + #[cfg(target_endian = "big")] + obj.parse_section(fake_section( + EbpfSectionKind::Btf, + ".BTF", + &[ + 235, 159, 1, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + ], + None, + )) + .unwrap(); + + #[cfg(target_endian = "little")] obj.parse_section(fake_section( EbpfSectionKind::BtfExt, ".BTF.ext", @@ -1613,6 +1626,17 @@ mod tests { None, )) .unwrap(); + #[cfg(target_endian = "big")] + obj.parse_section(fake_section( + EbpfSectionKind::BtfExt, + ".BTF.ext", + &[ + 235, 129, 1, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, + 0, 8, 0, 0, 0, 16, + ], + None, + )) + .unwrap(); let btf = obj.fixup_and_sanitize_btf(&BtfFeatures::default()).unwrap(); assert!(btf.is_none()); @@ -2588,6 +2612,7 @@ mod tests { // generated from: // objcopy --dump-section .BTF=test.btf ./target/bpfel-unknown-none/debug/multimap-btf.bpf.o // hexdump -v -e '7/1 "0x%02X, " 1/1 " 0x%02X,\n"' test.btf + #[cfg(target_endian = "little")] let data: &[u8] = &[ 0x9F, 0xEB, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x01, 0x00, 0x00, 0xF0, 0x01, 0x00, 0x00, 0xCC, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -2660,6 +2685,79 @@ mod tests { 0x63, 0x68, 0x61, 0x72, 0x00, 0x5F, 0x6C, 0x69, 0x63, 0x65, 0x6E, 0x73, 0x65, 0x00, 0x2E, 0x6D, 0x61, 0x70, 0x73, 0x00, 0x6C, 0x69, 0x63, 0x65, 0x6E, 0x73, 0x65, 0x00, ]; + #[cfg(target_endian = "big")] + let data: &[u8] = &[ + 0xEB, 0x9F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xCC, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x19, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2C, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0A, 0x00, 0x00, 0x00, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x45, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, + 0x00, 0x05, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x00, 0x60, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x4E, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x54, + 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x66, 0x0E, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x00, 0x70, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, + 0x01, 0xB0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0xB5, + 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x01, 0xBE, 0x0F, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x01, 0xC4, 0x0F, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x69, 0x6E, 0x74, 0x00, 0x5F, 0x5F, 0x41, 0x52, 0x52, 0x41, 0x59, + 0x5F, 0x53, 0x49, 0x5A, 0x45, 0x5F, 0x54, 0x59, 0x50, 0x45, 0x5F, 0x5F, 0x00, 0x5F, + 0x5F, 0x75, 0x33, 0x32, 0x00, 0x75, 0x6E, 0x73, 0x69, 0x67, 0x6E, 0x65, 0x64, 0x20, + 0x69, 0x6E, 0x74, 0x00, 0x5F, 0x5F, 0x75, 0x36, 0x34, 0x00, 0x75, 0x6E, 0x73, 0x69, + 0x67, 0x6E, 0x65, 0x64, 0x20, 0x6C, 0x6F, 0x6E, 0x67, 0x20, 0x6C, 0x6F, 0x6E, 0x67, + 0x00, 0x74, 0x79, 0x70, 0x65, 0x00, 0x6B, 0x65, 0x79, 0x00, 0x76, 0x61, 0x6C, 0x75, + 0x65, 0x00, 0x6D, 0x61, 0x78, 0x5F, 0x65, 0x6E, 0x74, 0x72, 0x69, 0x65, 0x73, 0x00, + 0x6D, 0x61, 0x70, 0x5F, 0x31, 0x00, 0x6D, 0x61, 0x70, 0x5F, 0x32, 0x00, 0x63, 0x74, + 0x78, 0x00, 0x62, 0x70, 0x66, 0x5F, 0x70, 0x72, 0x6F, 0x67, 0x00, 0x74, 0x72, 0x61, + 0x63, 0x65, 0x70, 0x6F, 0x69, 0x6E, 0x74, 0x00, 0x2F, 0x76, 0x61, 0x72, 0x2F, 0x68, + 0x6F, 0x6D, 0x65, 0x2F, 0x64, 0x61, 0x76, 0x65, 0x2F, 0x64, 0x65, 0x76, 0x2F, 0x61, + 0x79, 0x61, 0x2D, 0x72, 0x73, 0x2F, 0x61, 0x79, 0x61, 0x2F, 0x74, 0x65, 0x73, 0x74, + 0x2F, 0x69, 0x6E, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x2D, 0x65, + 0x62, 0x70, 0x66, 0x2F, 0x73, 0x72, 0x63, 0x2F, 0x62, 0x70, 0x66, 0x2F, 0x6D, 0x75, + 0x6C, 0x74, 0x69, 0x6D, 0x61, 0x70, 0x2D, 0x62, 0x74, 0x66, 0x2E, 0x62, 0x70, 0x66, + 0x2E, 0x63, 0x00, 0x69, 0x6E, 0x74, 0x20, 0x62, 0x70, 0x66, 0x5F, 0x70, 0x72, 0x6F, + 0x67, 0x28, 0x76, 0x6F, 0x69, 0x64, 0x20, 0x2A, 0x63, 0x74, 0x78, 0x29, 0x00, 0x09, + 0x5F, 0x5F, 0x75, 0x33, 0x32, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x3D, 0x20, 0x30, 0x3B, + 0x00, 0x09, 0x5F, 0x5F, 0x75, 0x36, 0x34, 0x20, 0x74, 0x77, 0x65, 0x6E, 0x74, 0x79, + 0x5F, 0x66, 0x6F, 0x75, 0x72, 0x20, 0x3D, 0x20, 0x32, 0x34, 0x3B, 0x00, 0x09, 0x5F, + 0x5F, 0x75, 0x36, 0x34, 0x20, 0x66, 0x6F, 0x72, 0x74, 0x79, 0x5F, 0x74, 0x77, 0x6F, + 0x20, 0x3D, 0x20, 0x34, 0x32, 0x3B, 0x00, 0x20, 0x20, 0x20, 0x20, 0x62, 0x70, 0x66, + 0x5F, 0x6D, 0x61, 0x70, 0x5F, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5F, 0x65, 0x6C, + 0x65, 0x6D, 0x28, 0x26, 0x6D, 0x61, 0x70, 0x5F, 0x31, 0x2C, 0x20, 0x26, 0x6B, 0x65, + 0x79, 0x2C, 0x20, 0x26, 0x74, 0x77, 0x65, 0x6E, 0x74, 0x79, 0x5F, 0x66, 0x6F, 0x75, + 0x72, 0x2C, 0x20, 0x42, 0x50, 0x46, 0x5F, 0x41, 0x4E, 0x59, 0x29, 0x3B, 0x00, 0x20, + 0x20, 0x20, 0x20, 0x62, 0x70, 0x66, 0x5F, 0x6D, 0x61, 0x70, 0x5F, 0x75, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x5F, 0x65, 0x6C, 0x65, 0x6D, 0x28, 0x26, 0x6D, 0x61, 0x70, 0x5F, + 0x32, 0x2C, 0x20, 0x26, 0x6B, 0x65, 0x79, 0x2C, 0x20, 0x26, 0x66, 0x6F, 0x72, 0x74, + 0x79, 0x5F, 0x74, 0x77, 0x6F, 0x2C, 0x20, 0x42, 0x50, 0x46, 0x5F, 0x41, 0x4E, 0x59, + 0x29, 0x3B, 0x00, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6E, 0x20, 0x30, 0x3B, 0x00, + 0x63, 0x68, 0x61, 0x72, 0x00, 0x5F, 0x6C, 0x69, 0x63, 0x65, 0x6E, 0x73, 0x65, 0x00, + 0x2E, 0x6D, 0x61, 0x70, 0x73, 0x00, 0x6C, 0x69, 0x63, 0x65, 0x6E, 0x73, 0x65, 0x00, + ]; let btf_section = fake_section(EbpfSectionKind::Btf, ".BTF", data, None); obj.parse_section(btf_section).unwrap(); diff --git a/aya/src/maps/perf/perf_buffer.rs b/aya/src/maps/perf/perf_buffer.rs index 56424637..79b799ee 100644 --- a/aya/src/maps/perf/perf_buffer.rs +++ b/aya/src/maps/perf/perf_buffer.rs @@ -547,8 +547,17 @@ mod tests { let offset = PAGE_SIZE - mem::size_of::() - 2; mmapped_buf.mmap_page.data_tail = offset as u64; write(&mut mmapped_buf, offset, header); - write(&mut mmapped_buf, PAGE_SIZE - 2, 0x0004u16); - write(&mut mmapped_buf, 0, 0x0000u16); + #[cfg(target_endian = "little")] + { + write(&mut mmapped_buf, PAGE_SIZE - 2, 0x0004u16); + write(&mut mmapped_buf, 0, 0x0000u16); + } + #[cfg(target_endian = "big")] + { + write(&mut mmapped_buf, PAGE_SIZE - 2, 0x0000u16); + write(&mut mmapped_buf, 0, 0x0004u16); + } + write(&mut mmapped_buf, 2, 0xBAADCAFEu32); let mut out_bufs = [BytesMut::with_capacity(8)]; @@ -579,13 +588,19 @@ mod tests { }, size: mem::size_of::() as u32, }, + #[cfg(target_endian = "little")] value: 0xCAFEBABEu32, + #[cfg(target_endian = "big")] + value: 0xBAADCAFEu32, }; let offset = PAGE_SIZE - mem::size_of::>(); mmapped_buf.mmap_page.data_tail = offset as u64; write(&mut mmapped_buf, offset, sample); + #[cfg(target_endian = "little")] write(&mut mmapped_buf, 0, 0xBAADCAFEu32); + #[cfg(target_endian = "big")] + write(&mut mmapped_buf, 0, 0xCAFEBABEu32); let mut out_bufs = [BytesMut::with_capacity(8)]; From b513af12e8baa5c5097eaf0afdae61a830c3f877 Mon Sep 17 00:00:00 2001 From: Billy McFall <22157057+Billy99@users.noreply.github.com> Date: Tue, 25 Jun 2024 18:19:21 -0400 Subject: [PATCH 2/4] aya: add archs powerpc64 and s390x to aya bpfman, a project using aya, has a requirement to support powerpc64 and s390x architectures. Adding these two architectures to aya. Signed-off-by: Billy McFall <22157057+Billy99@users.noreply.github.com> --- .cargo/config.toml | 6 ++ .github/workflows/ci.yml | 4 + Cargo.toml | 2 +- aya-obj/src/btf/relocation.rs | 2 +- aya-obj/src/generated/mod.rs | 8 ++ ebpf/aya-ebpf-bindings/build.rs | 2 +- ebpf/aya-ebpf-bindings/src/lib.rs | 10 ++ ebpf/aya-ebpf-bindings/src/powerpc64/mod.rs | 3 + ebpf/aya-ebpf-bindings/src/s390x/mod.rs | 3 + ebpf/aya-ebpf-cty/build.rs | 2 +- ebpf/aya-ebpf-cty/src/lib.rs | 6 ++ ebpf/aya-ebpf/build.rs | 2 +- ebpf/aya-ebpf/src/args.rs | 101 +++++++++++++++++++- ebpf/aya-ebpf/src/programs/probe.rs | 10 +- ebpf/aya-ebpf/src/programs/retprobe.rs | 10 +- 15 files changed, 159 insertions(+), 12 deletions(-) create mode 100644 ebpf/aya-ebpf-bindings/src/powerpc64/mod.rs create mode 100644 ebpf/aya-ebpf-bindings/src/s390x/mod.rs diff --git a/.cargo/config.toml b/.cargo/config.toml index 0c1258f6..674071ff 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -9,3 +9,9 @@ linker = "arm-linux-gnueabihf-gcc" [target.aarch64-unknown-linux-musl] linker = "aarch64-linux-musl-gcc" + +[target.powerpc64le-unknown-linux-gnu] +linker = "powerpc64le-linux-gnu-gcc" + +[target.s390x-unknown-linux-gnu] +linker = "s390x-linux-gnu-gcc" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 68553fb9..3e21cff5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,6 +72,8 @@ jobs: - aarch64-unknown-linux-gnu - armv7-unknown-linux-gnueabi - riscv64gc-unknown-linux-gnu + - powerpc64le-unknown-linux-gnu + - s390x-unknown-linux-gnu runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 @@ -135,6 +137,8 @@ jobs: - aarch64 - arm - riscv64 + - powerpc64 + - s390x target: - bpfel-unknown-none - bpfeb-unknown-none diff --git a/Cargo.toml b/Cargo.toml index 082ab9bd..7ee4e6b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,7 +40,7 @@ default-members = [ # ebpf crates are omitted; they must be built with: # --target bpfe{b,l}-unknown-none - # CARGO_CFG_BPF_TARGET_ARCH={x86_64,aarch64,arm,riscv64} + # CARGO_CFG_BPF_TARGET_ARCH={x86_64,aarch64,arm,riscv64,powerpc64,s390x} ] [workspace.package] diff --git a/aya-obj/src/btf/relocation.rs b/aya-obj/src/btf/relocation.rs index c9412c79..c78431df 100644 --- a/aya-obj/src/btf/relocation.rs +++ b/aya-obj/src/btf/relocation.rs @@ -1215,7 +1215,7 @@ impl ComputedRelocation { } #[cfg(target_endian = "big")] FieldLShift64 => { - value.value = (8 - byte_size) * 8 + (bit_off - byte_off * 8); + value.value = ((8 - byte_size) * 8 + (bit_off - byte_off * 8)) as u64; } FieldRShift64 => { value.value = 64 - bit_size as u64; diff --git a/aya-obj/src/generated/mod.rs b/aya-obj/src/generated/mod.rs index f9097937..bbb693b3 100644 --- a/aya-obj/src/generated/mod.rs +++ b/aya-obj/src/generated/mod.rs @@ -13,8 +13,12 @@ mod btf_internal_bindings; mod linux_bindings_aarch64; #[cfg(target_arch = "arm")] mod linux_bindings_armv7; +#[cfg(target_arch = "powerpc64")] +mod linux_bindings_powerpc64; #[cfg(target_arch = "riscv64")] mod linux_bindings_riscv64; +#[cfg(target_arch = "s390x")] +mod linux_bindings_s390x; #[cfg(target_arch = "x86_64")] mod linux_bindings_x86_64; @@ -25,7 +29,11 @@ pub use btf_internal_bindings::{bpf_core_relo, bpf_core_relo_kind, btf_ext_heade pub use linux_bindings_aarch64::*; #[cfg(target_arch = "arm")] pub use linux_bindings_armv7::*; +#[cfg(target_arch = "powerpc64")] +pub use linux_bindings_powerpc64::*; #[cfg(target_arch = "riscv64")] pub use linux_bindings_riscv64::*; +#[cfg(target_arch = "s390x")] +pub use linux_bindings_s390x::*; #[cfg(target_arch = "x86_64")] pub use linux_bindings_x86_64::*; diff --git a/ebpf/aya-ebpf-bindings/build.rs b/ebpf/aya-ebpf-bindings/build.rs index fde2d9e5..e491077d 100644 --- a/ebpf/aya-ebpf-bindings/build.rs +++ b/ebpf/aya-ebpf-bindings/build.rs @@ -9,5 +9,5 @@ fn main() { let arch = arch.split_once('-').map_or(&*arch, |x| x.0); println!("cargo:rustc-cfg=bpf_target_arch=\"{arch}\""); } - println!("cargo::rustc-check-cfg=cfg(bpf_target_arch, values(\"x86_64\",\"arm\",\"aarch64\",\"riscv64\"))"); + println!("cargo::rustc-check-cfg=cfg(bpf_target_arch, values(\"x86_64\",\"arm\",\"aarch64\",\"riscv64\",\"powerpc64\",\"s390x\"))"); } diff --git a/ebpf/aya-ebpf-bindings/src/lib.rs b/ebpf/aya-ebpf-bindings/src/lib.rs index b9037bac..0add58d9 100644 --- a/ebpf/aya-ebpf-bindings/src/lib.rs +++ b/ebpf/aya-ebpf-bindings/src/lib.rs @@ -14,13 +14,23 @@ mod aarch64; #[cfg(bpf_target_arch = "riscv64")] mod riscv64; +#[cfg(bpf_target_arch = "powerpc64")] +mod powerpc64; + +#[cfg(bpf_target_arch = "s390x")] +mod s390x; + mod gen { #[cfg(bpf_target_arch = "aarch64")] pub use super::aarch64::*; #[cfg(bpf_target_arch = "arm")] pub use super::armv7::*; + #[cfg(bpf_target_arch = "powerpc64")] + pub use super::powerpc64::*; #[cfg(bpf_target_arch = "riscv64")] pub use super::riscv64::*; + #[cfg(bpf_target_arch = "s390x")] + pub use super::s390x::*; #[cfg(bpf_target_arch = "x86_64")] pub use super::x86_64::*; } diff --git a/ebpf/aya-ebpf-bindings/src/powerpc64/mod.rs b/ebpf/aya-ebpf-bindings/src/powerpc64/mod.rs new file mode 100644 index 00000000..226884ea --- /dev/null +++ b/ebpf/aya-ebpf-bindings/src/powerpc64/mod.rs @@ -0,0 +1,3 @@ +#![allow(clippy::all, dead_code)] +pub mod bindings; +pub mod helpers; diff --git a/ebpf/aya-ebpf-bindings/src/s390x/mod.rs b/ebpf/aya-ebpf-bindings/src/s390x/mod.rs new file mode 100644 index 00000000..226884ea --- /dev/null +++ b/ebpf/aya-ebpf-bindings/src/s390x/mod.rs @@ -0,0 +1,3 @@ +#![allow(clippy::all, dead_code)] +pub mod bindings; +pub mod helpers; diff --git a/ebpf/aya-ebpf-cty/build.rs b/ebpf/aya-ebpf-cty/build.rs index 1488a7f2..8642bdbe 100644 --- a/ebpf/aya-ebpf-cty/build.rs +++ b/ebpf/aya-ebpf-cty/build.rs @@ -9,6 +9,6 @@ fn main() { let arch = arch.split_once('-').map_or(&*arch, |x| x.0); println!("cargo:rustc-cfg=bpf_target_arch=\"{arch}\""); } - println!("cargo::rustc-check-cfg=cfg(bpf_target_arch, values(\"x86_64\",\"arm\",\"aarch64\",\"riscv64\"))"); + println!("cargo::rustc-check-cfg=cfg(bpf_target_arch, values(\"x86_64\",\"arm\",\"aarch64\",\"riscv64\",\"powerpc64\",\"s390x\"))"); println!("cargo::rustc-check-cfg=cfg(target_arch, values(\"asmjs\",\"nvptx\",\"xtensa\"))"); } diff --git a/ebpf/aya-ebpf-cty/src/lib.rs b/ebpf/aya-ebpf-cty/src/lib.rs index b2530c12..d25b8505 100644 --- a/ebpf/aya-ebpf-cty/src/lib.rs +++ b/ebpf/aya-ebpf-cty/src/lib.rs @@ -24,9 +24,15 @@ mod ad { #[cfg(bpf_target_arch = "aarch64")] pub type c_char = super::c_uchar; + #[cfg(bpf_target_arch = "powerpc64")] + pub type c_char = super::c_uchar; + #[cfg(bpf_target_arch = "riscv64")] pub type c_char = super::c_uchar; + #[cfg(bpf_target_arch = "s390x")] + pub type c_char = super::c_uchar; + #[cfg(bpf_target_arch = "x86_64")] pub type c_char = super::c_schar; } diff --git a/ebpf/aya-ebpf/build.rs b/ebpf/aya-ebpf/build.rs index e087046a..38887c3b 100644 --- a/ebpf/aya-ebpf/build.rs +++ b/ebpf/aya-ebpf/build.rs @@ -10,7 +10,7 @@ fn main() { let arch = arch.split_once('-').map_or(&*arch, |x| x.0); println!("cargo:rustc-cfg=bpf_target_arch=\"{arch}\""); } - println!("cargo::rustc-check-cfg=cfg(bpf_target_arch, values(\"x86_64\",\"arm\",\"aarch64\",\"riscv64\"))"); + println!("cargo::rustc-check-cfg=cfg(bpf_target_arch, values(\"x86_64\",\"arm\",\"aarch64\",\"riscv64\",\"powerpc64\",\"s390x\"))"); println!("cargo::rustc-check-cfg=cfg(unstable)"); } diff --git a/ebpf/aya-ebpf/src/args.rs b/ebpf/aya-ebpf/src/args.rs index 7cee97a8..72023e0d 100644 --- a/ebpf/aya-ebpf/src/args.rs +++ b/ebpf/aya-ebpf/src/args.rs @@ -1,8 +1,13 @@ -// aarch64 uses user_pt_regs instead of pt_regs -#[cfg(not(any(bpf_target_arch = "aarch64", bpf_target_arch = "riscv64")))] +#[cfg(any( + bpf_target_arch = "x86_64", + bpf_target_arch = "arm", + bpf_target_arch = "powerpc64" +))] use crate::bindings::pt_regs; -#[cfg(bpf_target_arch = "aarch64")] +// aarch64 uses user_pt_regs instead of pt_regs +#[cfg(any(bpf_target_arch = "aarch64", bpf_target_arch = "s390x"))] use crate::bindings::user_pt_regs as pt_regs; +// riscv64 uses user_regs_struct instead of pt_regs #[cfg(bpf_target_arch = "riscv64")] use crate::bindings::user_regs_struct as pt_regs; use crate::{cty::c_void, helpers::bpf_probe_read}; @@ -168,6 +173,36 @@ impl FromPtRegs for *const T { } } +#[cfg(bpf_target_arch = "powerpc64")] +impl FromPtRegs for *const T { + fn from_argument(ctx: &pt_regs, n: usize) -> Option { + if n <= 7 { + unsafe { bpf_probe_read(&ctx.gpr[3 + n]).map(|v| v as *const _).ok() } + } else { + None + } + } + + fn from_retval(ctx: &pt_regs) -> Option { + unsafe { bpf_probe_read(&ctx.gpr[3]).map(|v| v as *const _).ok() } + } +} + +#[cfg(bpf_target_arch = "s390x")] +impl FromPtRegs for *const T { + fn from_argument(ctx: &pt_regs, n: usize) -> Option { + if n <= 4 { + unsafe { bpf_probe_read(&ctx.gprs[2 + n]).map(|v| v as *const _).ok() } + } else { + None + } + } + + fn from_retval(ctx: &pt_regs) -> Option { + unsafe { bpf_probe_read(&ctx.gprs[2]).map(|v| v as *const _).ok() } + } +} + #[cfg(bpf_target_arch = "x86_64")] impl FromPtRegs for *mut T { fn from_argument(ctx: &pt_regs, n: usize) -> Option { @@ -238,6 +273,36 @@ impl FromPtRegs for *mut T { } } +#[cfg(bpf_target_arch = "powerpc64")] +impl FromPtRegs for *mut T { + fn from_argument(ctx: &pt_regs, n: usize) -> Option { + if n <= 7 { + unsafe { bpf_probe_read(&ctx.gpr[3 + n]).map(|v| v as *mut _).ok() } + } else { + None + } + } + + fn from_retval(ctx: &pt_regs) -> Option { + unsafe { bpf_probe_read(&ctx.gpr[3]).map(|v| v as *mut _).ok() } + } +} + +#[cfg(bpf_target_arch = "s390x")] +impl FromPtRegs for *mut T { + fn from_argument(ctx: &pt_regs, n: usize) -> Option { + if n <= 4 { + unsafe { bpf_probe_read(&ctx.gprs[2 + n]).map(|v| v as *mut _).ok() } + } else { + None + } + } + + fn from_retval(ctx: &pt_regs) -> Option { + unsafe { bpf_probe_read(&ctx.gprs[2]).map(|v| v as *mut _).ok() } + } +} + /// Helper macro to implement [`FromPtRegs`] for a primitive type. macro_rules! impl_from_pt_regs { ($type:ident) => { @@ -310,6 +375,36 @@ macro_rules! impl_from_pt_regs { Some(ctx.ra as *const $type as _) } } + + #[cfg(bpf_target_arch = "powerpc64")] + impl FromPtRegs for $type { + fn from_argument(ctx: &pt_regs, n: usize) -> Option { + if n <= 7 { + Some(ctx.gpr[3 + n] as *const $type as _) + } else { + None + } + } + + fn from_retval(ctx: &pt_regs) -> Option { + Some(ctx.gpr[3] as *const $type as _) + } + } + + #[cfg(bpf_target_arch = "s390x")] + impl FromPtRegs for $type { + fn from_argument(ctx: &pt_regs, n: usize) -> Option { + if n <= 4 { + Some(ctx.gprs[2 + n] as *const $type as _) + } else { + None + } + } + + fn from_retval(ctx: &pt_regs) -> Option { + Some(ctx.gprs[2] as *const $type as _) + } + } }; } diff --git a/ebpf/aya-ebpf/src/programs/probe.rs b/ebpf/aya-ebpf/src/programs/probe.rs index 3f9b965b..8507c0be 100644 --- a/ebpf/aya-ebpf/src/programs/probe.rs +++ b/ebpf/aya-ebpf/src/programs/probe.rs @@ -1,9 +1,15 @@ use core::ffi::c_void; -#[cfg(not(any(bpf_target_arch = "aarch64", bpf_target_arch = "riscv64")))] +#[cfg(any( + bpf_target_arch = "x86_64", + bpf_target_arch = "arm", + bpf_target_arch = "powerpc64" +))] use crate::bindings::pt_regs; -#[cfg(bpf_target_arch = "aarch64")] +// aarch64 uses user_pt_regs instead of pt_regs +#[cfg(any(bpf_target_arch = "aarch64", bpf_target_arch = "s390x"))] use crate::bindings::user_pt_regs as pt_regs; +// riscv64 uses user_regs_struct instead of pt_regs #[cfg(bpf_target_arch = "riscv64")] use crate::bindings::user_regs_struct as pt_regs; use crate::{args::FromPtRegs, EbpfContext}; diff --git a/ebpf/aya-ebpf/src/programs/retprobe.rs b/ebpf/aya-ebpf/src/programs/retprobe.rs index 2cff9b55..f271473b 100644 --- a/ebpf/aya-ebpf/src/programs/retprobe.rs +++ b/ebpf/aya-ebpf/src/programs/retprobe.rs @@ -1,9 +1,15 @@ use core::ffi::c_void; -#[cfg(not(any(bpf_target_arch = "aarch64", bpf_target_arch = "riscv64")))] +#[cfg(any( + bpf_target_arch = "x86_64", + bpf_target_arch = "arm", + bpf_target_arch = "powerpc64" +))] use crate::bindings::pt_regs; -#[cfg(bpf_target_arch = "aarch64")] +// aarch64 uses user_pt_regs instead of pt_regs +#[cfg(any(bpf_target_arch = "aarch64", bpf_target_arch = "s390x"))] use crate::bindings::user_pt_regs as pt_regs; +// riscv64 uses user_regs_struct instead of pt_regs #[cfg(bpf_target_arch = "riscv64")] use crate::bindings::user_regs_struct as pt_regs; use crate::{args::FromPtRegs, EbpfContext}; From cd1db86fd490b3c0f03229bd8999a2e67ccecfc4 Mon Sep 17 00:00:00 2001 From: Billy McFall <22157057+Billy99@users.noreply.github.com> Date: Tue, 23 Jul 2024 13:59:15 -0400 Subject: [PATCH 3/4] aya: adjust bpf programs for big endian In aya/src/sys/bpf.rs, there are several simple bpf programs written as byte arrays. These need to be adjusted to account for big endian. Signed-off-by: Billy McFall <22157057+Billy99@users.noreply.github.com> --- aya/src/sys/bpf.rs | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/aya/src/sys/bpf.rs b/aya/src/sys/bpf.rs index f327d2bb..66a1e89c 100644 --- a/aya/src/sys/bpf.rs +++ b/aya/src/sys/bpf.rs @@ -672,6 +672,11 @@ pub(crate) fn is_prog_name_supported() -> bool { }); u.prog_name = name; + // The fields conforming an encoded basic instruction are stored in the following order: + // opcode:8 src_reg:4 dst_reg:4 offset:16 imm:32 - In little-endian BPF. + // opcode:8 dst_reg:4 src_reg:4 offset:16 imm:32 - In big-endian BPF. + // Multi-byte fields ('imm' and 'offset') are stored using endian order. + // https://www.kernel.org/doc/html/v6.4-rc7/bpf/instruction-set.html#instruction-encoding let prog: &[u8] = &[ 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov64 r0 = 0 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exit @@ -692,6 +697,12 @@ pub(crate) fn is_probe_read_kernel_supported() -> bool { let mut attr = unsafe { mem::zeroed::() }; let u = unsafe { &mut attr.__bindgen_anon_3 }; + // The fields conforming an encoded basic instruction are stored in the following order: + // opcode:8 src_reg:4 dst_reg:4 offset:16 imm:32 - In little-endian BPF. + // opcode:8 dst_reg:4 src_reg:4 offset:16 imm:32 - In big-endian BPF. + // Multi-byte fields ('imm' and 'offset') are stored using endian order. + // https://www.kernel.org/doc/html/v6.4-rc7/bpf/instruction-set.html#instruction-encoding + #[cfg(target_endian = "little")] let prog: &[u8] = &[ 0xbf, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // r1 = r10 0x07, 0x01, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, // r1 -= 8 @@ -700,6 +711,15 @@ pub(crate) fn is_probe_read_kernel_supported() -> bool { 0x85, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, // call 113 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exit ]; + #[cfg(target_endian = "big")] + let prog: &[u8] = &[ + 0xbf, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // r1 = r10 + 0x07, 0x10, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf8, // r1 -= 8 + 0xb7, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, // r2 = 8 + 0xb7, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // r3 = 0 + 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, // call 113 + 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exit + ]; let gpl = b"GPL\0"; u.license = gpl.as_ptr() as u64; @@ -716,6 +736,11 @@ pub(crate) fn is_perf_link_supported() -> bool { let mut attr = unsafe { mem::zeroed::() }; let u = unsafe { &mut attr.__bindgen_anon_3 }; + // The fields conforming an encoded basic instruction are stored in the following order: + // opcode:8 src_reg:4 dst_reg:4 offset:16 imm:32 - In little-endian BPF. + // opcode:8 dst_reg:4 src_reg:4 offset:16 imm:32 - In big-endian BPF. + // Multi-byte fields ('imm' and 'offset') are stored using endian order. + // https://www.kernel.org/doc/html/v6.4-rc7/bpf/instruction-set.html#instruction-encoding let prog: &[u8] = &[ 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov64 r0 = 0 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exit @@ -746,6 +771,12 @@ pub(crate) fn is_bpf_global_data_supported() -> bool { let mut attr = unsafe { mem::zeroed::() }; let u = unsafe { &mut attr.__bindgen_anon_3 }; + // The fields conforming an encoded basic instruction are stored in the following order: + // opcode:8 src_reg:4 dst_reg:4 offset:16 imm:32 - In little-endian BPF. + // opcode:8 dst_reg:4 src_reg:4 offset:16 imm:32 - In big-endian BPF. + // Multi-byte fields ('imm' and 'offset') are stored using endian order. + // https://www.kernel.org/doc/html/v6.4-rc7/bpf/instruction-set.html#instruction-encoding + #[cfg(target_endian = "little")] let prog: &[u8] = &[ 0x18, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ld_pseudo r1, 0x2, 0x0 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // @@ -753,6 +784,14 @@ pub(crate) fn is_bpf_global_data_supported() -> bool { 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov64 r0 = 0 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exit ]; + #[cfg(target_endian = "big")] + let prog: &[u8] = &[ + 0x18, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, // ld_pseudo r1, 0x2, 0x0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // + 0x7a, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, // stdw [r1 + 0x0], 0x2a + 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov64 r0 = 0 + 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exit + ]; let mut insns = copy_instructions(prog).unwrap(); @@ -793,10 +832,21 @@ pub(crate) fn is_bpf_cookie_supported() -> bool { let mut attr = unsafe { mem::zeroed::() }; let u = unsafe { &mut attr.__bindgen_anon_3 }; + // The fields conforming an encoded basic instruction are stored in the following order: + // opcode:8 src_reg:4 dst_reg:4 offset:16 imm:32 - In little-endian BPF. + // opcode:8 dst_reg:4 src_reg:4 offset:16 imm:32 - In big-endian BPF. + // Multi-byte fields ('imm' and 'offset') are stored using endian order. + // https://www.kernel.org/doc/html/v6.4-rc7/bpf/instruction-set.html#instruction-encoding + #[cfg(target_endian = "little")] let prog: &[u8] = &[ 0x85, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, // call bpf_get_attach_cookie 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exit ]; + #[cfg(target_endian = "big")] + let prog: &[u8] = &[ + 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, // call bpf_get_attach_cookie + 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exit + ]; let gpl = b"GPL\0"; u.license = gpl.as_ptr() as u64; From 4dc4b5ccd48bd86e2cc59ad7386514c1531450af Mon Sep 17 00:00:00 2001 From: Billy McFall <22157057+Billy99@users.noreply.github.com> Date: Thu, 25 Jul 2024 11:41:23 -0400 Subject: [PATCH 4/4] test: adjust test to not use byte arrays Where possible, replace the hardcoded byte arrays in the tests with the structs they represent, then convert the structs to byte arrays. Signed-off-by: Billy McFall <22157057+Billy99@users.noreply.github.com> --- aya-obj/src/btf/btf.rs | 137 ++++++++++++------- aya-obj/src/btf/types.rs | 286 ++++++++++----------------------------- aya-obj/src/obj.rs | 59 ++++---- 3 files changed, 185 insertions(+), 297 deletions(-) diff --git a/aya-obj/src/btf/btf.rs b/aya-obj/src/btf/btf.rs index 9fbdc496..0d160a7d 100644 --- a/aya-obj/src/btf/btf.rs +++ b/aya-obj/src/btf/btf.rs @@ -1110,17 +1110,18 @@ mod tests { #[test] fn test_parse_header() { - #[cfg(target_endian = "little")] - let data: &[u8] = &[ - 0x9f, 0xeb, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x54, - 0x2a, 0x00, 0x64, 0x54, 0x2a, 0x00, 0x10, 0x64, 0x1c, 0x00, - ]; - #[cfg(target_endian = "big")] - let data: &[u8] = &[ - 0xeb, 0x9f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, - 0x54, 0x64, 0x00, 0x2a, 0x54, 0x64, 0x00, 0x1c, 0x64, 0x10, - ]; - let header = unsafe { read_btf_header(data) }; + let header = btf_header { + magic: 0xeb9f, + version: 0x01, + flags: 0x00, + hdr_len: 0x18, + type_off: 0x00, + type_len: 0x2a5464, + str_off: 0x2a5464, + str_len: 0x1c6410, + }; + let data = unsafe { bytes_of::(&header).to_vec() }; + let header = unsafe { read_btf_header(&data) }; assert_eq!(header.magic, 0xeb9f); assert_eq!(header.version, 0x01); assert_eq!(header.flags, 0x00); @@ -1221,51 +1222,88 @@ mod tests { assert_eq!(data2.len(), 517); assert_eq!(data, data2); - #[cfg(target_endian = "little")] - let ext_data: &[u8] = &[ - 0x9f, 0xeb, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, - 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x72, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x00, - 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0x05, 0x2c, 0x00, 0x00, - ]; - #[cfg(target_endian = "big")] - let ext_data: &[u8] = &[ - 0xeb, 0x9f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x7b, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x2c, 0x05, - ]; + const FUNC_LEN: u32 = 0x14; + const LINE_INFO_LEN: u32 = 0x1c; + const CORE_RELO_LEN: u32 = 0; + const DATA_LEN: u32 = (FUNC_LEN + LINE_INFO_LEN + CORE_RELO_LEN) / 4; + struct TestStruct { + _header: btf_ext_header, + _data: [u32; DATA_LEN as usize], + } + let test_data = TestStruct { + _header: btf_ext_header { + magic: 0xeb9f, + version: 1, + flags: 0, + hdr_len: 0x20, + func_info_off: 0, + func_info_len: FUNC_LEN, + line_info_off: FUNC_LEN, + line_info_len: LINE_INFO_LEN, + core_relo_off: FUNC_LEN + LINE_INFO_LEN, + core_relo_len: CORE_RELO_LEN, + }, + _data: [ + 0x00000008u32, + 0x00000072u32, + 0x00000001u32, + 0x00000000u32, + 0x00000007u32, + 0x00000010u32, + 0x00000072u32, + 0x00000001u32, + 0x00000000u32, + 0x0000007bu32, + 0x000000a2u32, + 0x00002c05u32, + ], + }; + let ext_data = unsafe { bytes_of::(&test_data).to_vec() }; assert_eq!(ext_data.len(), 80); - let _: BtfExt = BtfExt::parse(ext_data, Endianness::default(), &btf) + let _: BtfExt = BtfExt::parse(&ext_data, Endianness::default(), &btf) .unwrap_or_else(|e| panic!("{}", e)); } #[test] fn parsing_older_ext_data() { - #[cfg(target_endian = "little")] - let btf_data = [ - 159, 235, 1, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - ]; - #[cfg(target_endian = "big")] - let btf_data = [ - 235, 159, 1, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - ]; - - #[cfg(target_endian = "little")] - let btf_ext_data = [ - 159, 235, 1, 0, 24, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, - 0, 16, 0, 0, 0, - ]; - #[cfg(target_endian = "big")] - let btf_ext_data = [ - 235, 159, 1, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, - 8, 0, 0, 0, 16, - ]; + const TYPE_LEN: u32 = 0; + const STR_LEN: u32 = 1; + struct BtfTestStruct { + _header: btf_header, + _data: [u8; (TYPE_LEN + STR_LEN) as usize], + } + let btf_test_data = BtfTestStruct { + _header: btf_header { + magic: 0xeb9f, + version: 0x01, + flags: 0x00, + hdr_len: 24, + type_off: 0, + type_len: TYPE_LEN, + str_off: TYPE_LEN, + str_len: TYPE_LEN + STR_LEN, + }, + _data: [0x00u8], + }; + let btf_data = unsafe { bytes_of::(&btf_test_data).to_vec() }; + + const FUNC_INFO_LEN: u32 = 4; + const LINE_INFO_LEN: u32 = 4; + const CORE_RELO_LEN: u32 = 16; + let ext_header = btf_ext_header { + magic: 0xeb9f, + version: 1, + flags: 0, + hdr_len: 24, + func_info_off: 0, + func_info_len: FUNC_INFO_LEN, + line_info_off: FUNC_INFO_LEN, + line_info_len: LINE_INFO_LEN, + core_relo_off: FUNC_INFO_LEN + LINE_INFO_LEN, + core_relo_len: CORE_RELO_LEN, + }; + let btf_ext_data = unsafe { bytes_of::(&ext_header).to_vec() }; let btf = Btf::parse(&btf_data, Endianness::default()).unwrap(); let btf_ext = BtfExt::parse(&btf_ext_data, Endianness::default(), &btf).unwrap(); @@ -1771,6 +1809,7 @@ mod tests { Btf::parse(&raw, Endianness::default()).unwrap(); } + // Not possible to emulate file system file "/sys/kernel/btf/vmlinux" as big endian, so skip #[test] #[cfg(feature = "std")] #[cfg_attr(miri, ignore = "`open` not available when isolation is enabled")] diff --git a/aya-obj/src/btf/types.rs b/aya-obj/src/btf/types.rs index a4190ea7..9e68b71c 100644 --- a/aya-obj/src/btf/types.rs +++ b/aya-obj/src/btf/types.rs @@ -662,7 +662,8 @@ pub struct Union { impl Union { pub(crate) fn new(name_offset: u32, size: u32, members: Vec) -> Self { - let info = (BtfKind::Union as u32) << 24; + let mut info = (BtfKind::Union as u32) << 24; + info |= (members.len() as u32) & 0xFFFF; Self { name_offset, info, @@ -1577,16 +1578,8 @@ mod tests { #[test] fn test_read_btf_type_int() { let endianness = Endianness::default(); - #[cfg(target_endian = "little")] - let data: &[u8] = &[ - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x40, 0x00, - 0x00, 0x00, - ]; - #[cfg(target_endian = "big")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x00, 0x40, - ]; + let bpf_type = BtfType::Int(Int::new(1, 8, IntEncoding::None, 0)); + let data: &[u8] = &bpf_type.to_bytes(); assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Int(new @ Int { name_offset, info: _, @@ -1600,65 +1593,11 @@ mod tests { }); } - #[test] - fn test_write_btf_long_unsigned_int() { - #[cfg(target_endian = "little")] - let data: &[u8] = &[ - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x40, 0x00, - 0x00, 0x00, - ]; - #[cfg(target_endian = "big")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x00, 0x40, - ]; - let int = Int::new(1, 8, IntEncoding::None, 0); - assert_eq!(int.to_bytes(), data); - } - - #[test] - fn test_write_btf_uchar() { - #[cfg(target_endian = "little")] - let data: &[u8] = &[ - 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x00, - ]; - #[cfg(target_endian = "big")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x08, - ]; - let int = Int::new(0x13, 1, IntEncoding::None, 0); - assert_eq!(int.to_bytes(), data); - } - - #[test] - fn test_write_btf_signed_short_int() { - #[cfg(target_endian = "little")] - let data: &[u8] = &[ - 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, - 0x00, 0x01, - ]; - #[cfg(target_endian = "big")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x4a, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, - 0x00, 0x10, - ]; - let int = Int::new(0x4a, 2, IntEncoding::Signed, 0); - assert_eq!(int.to_bytes(), data); - } - #[test] fn test_read_btf_type_ptr() { let endianness = Endianness::default(); - #[cfg(target_endian = "little")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x00, - ]; - #[cfg(target_endian = "big")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, - ]; + let bpf_type = BtfType::Ptr(Ptr::new(0, 0x06)); + let data: &[u8] = &bpf_type.to_bytes(); assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Ptr(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1667,16 +1606,8 @@ mod tests { #[test] fn test_read_btf_type_array() { let endianness = Endianness::default(); - #[cfg(target_endian = "little")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - ]; - #[cfg(target_endian = "big")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x02, - ]; + let bpf_type = BtfType::Array(Array::new(0, 1, 0x12, 2)); + let data: &[u8] = &bpf_type.to_bytes(); assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Array(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1685,16 +1616,13 @@ mod tests { #[test] fn test_read_btf_type_struct() { let endianness = Endianness::default(); - #[cfg(target_endian = "little")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x47, 0x02, - 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - ]; - #[cfg(target_endian = "big")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x02, 0x47, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, - ]; + let members = vec![BtfMember { + name_offset: 0x0247, + btf_type: 0x12, + offset: 0, + }]; + let bpf_type = BtfType::Struct(Struct::new(0, members, 4)); + let data: &[u8] = &bpf_type.to_bytes(); assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Struct(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1703,16 +1631,13 @@ mod tests { #[test] fn test_read_btf_type_union() { let endianness = Endianness::default(); - #[cfg(target_endian = "little")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0x04, 0x00, 0x00, 0x00, 0x0d, 0x04, - 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - ]; - #[cfg(target_endian = "big")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x0d, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, - ]; + let members = vec![BtfMember { + name_offset: 0x040d, + btf_type: 0x68, + offset: 0, + }]; + let bpf_type = BtfType::Union(Union::new(0, 4, members)); + let data: &[u8] = &bpf_type.to_bytes(); assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Union(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1721,16 +1646,11 @@ mod tests { #[test] fn test_read_btf_type_enum() { let endianness = Endianness::default(); - #[cfg(target_endian = "little")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x00, 0xc9, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - ]; - #[cfg(target_endian = "big")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x00, 0xc9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0x00, 0x01, - ]; + let enum1 = BtfEnum::new(0xc9, 0); + let enum2 = BtfEnum::new(0xcf, 1); + let variants = vec![enum1, enum2]; + let bpf_type = BtfType::Enum(Enum::new(0, false, variants)); + let data: &[u8] = &bpf_type.to_bytes(); assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Enum(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1739,14 +1659,13 @@ mod tests { #[test] fn test_read_btf_type_fwd() { let endianness = Endianness::default(); - #[cfg(target_endian = "little")] - let data: &[u8] = &[ - 0x0b, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, - ]; - #[cfg(target_endian = "big")] - let data: &[u8] = &[ - 0x00, 0x00, 0x55, 0x0b, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - ]; + let info = (BtfKind::Fwd as u32) << 24; + let bpf_type = BtfType::Fwd(Fwd { + name_offset: 0x550b, + info, + _unused: 0, + }); + let data: &[u8] = &bpf_type.to_bytes(); assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Fwd(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1755,14 +1674,8 @@ mod tests { #[test] fn test_read_btf_type_typedef() { let endianness = Endianness::default(); - #[cfg(target_endian = "little")] - let data: &[u8] = &[ - 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0b, 0x00, 0x00, 0x00, - ]; - #[cfg(target_endian = "big")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x31, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, - ]; + let bpf_type = BtfType::Typedef(Typedef::new(0x31, 0x0b)); + let data: &[u8] = &bpf_type.to_bytes(); assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Typedef(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1771,14 +1684,13 @@ mod tests { #[test] fn test_read_btf_type_volatile() { let endianness = Endianness::default(); - #[cfg(target_endian = "little")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x24, 0x00, 0x00, 0x00, - ]; - #[cfg(target_endian = "big")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, - ]; + let info = (BtfKind::Volatile as u32) << 24; + let bpf_type = BtfType::Volatile(Volatile { + name_offset: 0, + info, + btf_type: 0x24, + }); + let data: &[u8] = &bpf_type.to_bytes(); assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Volatile(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1787,14 +1699,8 @@ mod tests { #[test] fn test_read_btf_type_const() { let endianness = Endianness::default(); - #[cfg(target_endian = "little")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x00, - ]; - #[cfg(target_endian = "big")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - ]; + let bpf_type = BtfType::Const(Const::new(1)); + let data: &[u8] = &bpf_type.to_bytes(); assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Const(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1803,14 +1709,13 @@ mod tests { #[test] fn test_read_btf_type_restrict() { let endianness = Endianness::default(); - #[cfg(target_endian = "little")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x04, 0x00, 0x00, 0x00, - ]; - #[cfg(target_endian = "big")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - ]; + let info = (BtfKind::Restrict as u32) << 24; + let bpf_type = BtfType::Restrict(Restrict { + name_offset: 0, + _info: info, + btf_type: 4, + }); + let data: &[u8] = &bpf_type.to_bytes(); assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Restrict(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1819,14 +1724,8 @@ mod tests { #[test] fn test_read_btf_type_func() { let endianness = Endianness::default(); - #[cfg(target_endian = "little")] - let data: &[u8] = &[ - 0x17, 0x8b, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xf0, 0xe4, 0x00, 0x00, - ]; - #[cfg(target_endian = "big")] - let data: &[u8] = &[ - 0x00, 0x0f, 0x8b, 0x17, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xf0, - ]; + let bpf_type = BtfType::Func(Func::new(0x000f8b17, 0xe4f0, FuncLinkage::Global)); + let data: &[u8] = &bpf_type.to_bytes(); assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Func(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1835,16 +1734,12 @@ mod tests { #[test] fn test_read_btf_type_func_proto() { let endianness = Endianness::default(); - #[cfg(target_endian = "little")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, - ]; - #[cfg(target_endian = "big")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, - ]; + let params = vec![BtfParam { + name_offset: 0, + btf_type: 0x12, + }]; + let bpf_type = BtfType::FuncProto(FuncProto::new(params, 0)); + let data: &[u8] = &bpf_type.to_bytes(); assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::FuncProto(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1854,16 +1749,8 @@ mod tests { fn test_read_btf_type_func_var() { let endianness = Endianness::default(); // NOTE: There was no data in /sys/kernell/btf/vmlinux for this type - #[cfg(target_endian = "little")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, - ]; - #[cfg(target_endian = "big")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, - 0x00, 0x00, - ]; + let bpf_type = BtfType::Var(Var::new(0, 0xf0, VarLinkage::Static)); + let data: &[u8] = &bpf_type.to_bytes(); assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Var(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1872,16 +1759,13 @@ mod tests { #[test] fn test_read_btf_type_func_datasec() { let endianness = Endianness::default(); - #[cfg(target_endian = "little")] - let data: &[u8] = &[ - 0xd9, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - ]; - #[cfg(target_endian = "big")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0xd9, 0x0f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, - ]; + let entries = vec![DataSecEntry { + btf_type: 11, + offset: 0, + size: 4, + }]; + let bpf_type = BtfType::DataSec(DataSec::new(0xd9, entries, 0)); + let data: &[u8] = &bpf_type.to_bytes(); assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::DataSec(DataSec { name_offset: _, info: _, @@ -1903,14 +1787,8 @@ mod tests { #[test] fn test_read_btf_type_float() { let endianness = Endianness::default(); - #[cfg(target_endian = "little")] - let data: &[u8] = &[ - 0x78, 0xfd, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x00, - ]; - #[cfg(target_endian = "big")] - let data: &[u8] = &[ - 0x00, 0x02, 0xfd, 0x78, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, - ]; + let bpf_type = BtfType::Float(Float::new(0x02fd, 8)); + let data: &[u8] = &bpf_type.to_bytes(); assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Float(got) => { assert_eq!(got.to_bytes(), data); }); @@ -1962,25 +1840,9 @@ mod tests { #[test] pub fn test_read_btf_type_enum64() { let endianness = Endianness::default(); - #[cfg(target_endian = "little")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, // name offset - 0x01, 0x00, 0x00, 0x13, // info: vlen, type_kind - 0x08, 0x00, 0x00, 0x00, // size - 0xd7, 0x06, 0x00, 0x00, // enum variant name offset - 0xbb, 0xbb, 0xbb, 0xbb, // enum variant low - 0xaa, 0xaa, 0xaa, 0xaa, // enum variant high - ]; - #[cfg(target_endian = "big")] - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, // name offset - 0x13, 0x00, 0x00, 0x01, // info: vlen, type_kind - 0x00, 0x00, 0x00, 0x08, // size - 0x00, 0x00, 0x06, 0xd7, // enum variant name offset - 0xbb, 0xbb, 0xbb, 0xbb, // enum variant low - 0xaa, 0xaa, 0xaa, 0xaa, // enum variant high - ]; - + let variants = vec![BtfEnum64::new(0, 0xbbbbbbbbaaaaaaaau64)]; + let bpf_type = BtfType::Enum64(Enum64::new(0, false, variants)); + let data: &[u8] = &bpf_type.to_bytes(); assert_matches!(unsafe { BtfType::read(data, endianness) }.unwrap(), BtfType::Enum64(got) => { assert_eq!(got.to_bytes(), data); }); diff --git a/aya-obj/src/obj.rs b/aya-obj/src/obj.rs index 4c172e8e..429388a0 100644 --- a/aya-obj/src/obj.rs +++ b/aya-obj/src/obj.rs @@ -1396,6 +1396,7 @@ mod tests { use assert_matches::assert_matches; use super::*; + use crate::generated::btf_ext_header; const FAKE_INS_LEN: u64 = 8; @@ -1594,46 +1595,32 @@ mod tests { #[test] fn sanitizes_empty_btf_files_to_none() { let mut obj = fake_obj(); - #[cfg(target_endian = "little")] - obj.parse_section(fake_section( - EbpfSectionKind::Btf, - ".BTF", - &[ - 159, 235, 1, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - ], - None, - )) - .unwrap(); - #[cfg(target_endian = "big")] - obj.parse_section(fake_section( - EbpfSectionKind::Btf, - ".BTF", - &[ - 235, 159, 1, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - ], - None, - )) - .unwrap(); - #[cfg(target_endian = "little")] - obj.parse_section(fake_section( - EbpfSectionKind::BtfExt, - ".BTF.ext", - &[ - 159, 235, 1, 0, 24, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, - 0, 0, 16, 0, 0, 0, - ], - None, - )) - .unwrap(); - #[cfg(target_endian = "big")] + let btf = Btf::new(); + let btf_bytes = btf.to_bytes(); + obj.parse_section(fake_section(EbpfSectionKind::Btf, ".BTF", &btf_bytes, None)) + .unwrap(); + + const FUNC_INFO_LEN: u32 = 4; + const LINE_INFO_LEN: u32 = 4; + const CORE_RELO_LEN: u32 = 16; + let ext_header = btf_ext_header { + magic: 0xeb9f, + version: 1, + flags: 0, + hdr_len: 24, + func_info_off: 0, + func_info_len: FUNC_INFO_LEN, + line_info_off: FUNC_INFO_LEN, + line_info_len: LINE_INFO_LEN, + core_relo_off: FUNC_INFO_LEN + LINE_INFO_LEN, + core_relo_len: CORE_RELO_LEN, + }; + let btf_ext_bytes = bytes_of::(&ext_header).to_vec(); obj.parse_section(fake_section( EbpfSectionKind::BtfExt, ".BTF.ext", - &[ - 235, 129, 1, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, - 0, 8, 0, 0, 0, 16, - ], + &btf_ext_bytes, None, )) .unwrap();