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-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..0d160a7d 100644 --- a/aya-obj/src/btf/btf.rs +++ b/aya-obj/src/btf/btf.rs @@ -1110,11 +1110,18 @@ mod tests { #[test] fn test_parse_header() { - 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, - ]; - 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); @@ -1129,6 +1136,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,35 +1176,135 @@ 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); - 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, - ]; + 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() { - 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, - ]; - 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, - ]; + 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(); assert_eq!(btf_ext.func_info_rec_size(), 8); @@ -1701,9 +1809,11 @@ 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")] + #[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/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/btf/types.rs b/aya-obj/src/btf/types.rs index 89b1713b..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,10 +1578,8 @@ mod tests { #[test] fn test_read_btf_type_int() { let endianness = Endianness::default(); - let data: &[u8] = &[ - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x40, 0x00, - 0x00, 0x00, - ]; + 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: _, @@ -1594,42 +1593,11 @@ mod tests { }); } - #[test] - fn test_write_btf_long_unsigned_int() { - let data: &[u8] = &[ - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00, 0x40, 0x00, - 0x00, 0x00, - ]; - let int = Int::new(1, 8, IntEncoding::None, 0); - assert_eq!(int.to_bytes(), data); - } - - #[test] - fn test_write_btf_uchar() { - let data: &[u8] = &[ - 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x00, - ]; - let int = Int::new(0x13, 1, IntEncoding::None, 0); - assert_eq!(int.to_bytes(), data); - } - - #[test] - fn test_write_btf_signed_short_int() { - let data: &[u8] = &[ - 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, - 0x00, 0x01, - ]; - 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(); - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x00, - ]; + 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); }); @@ -1638,10 +1606,8 @@ mod tests { #[test] fn test_read_btf_type_array() { let endianness = Endianness::default(); - 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, - ]; + 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); }); @@ -1650,10 +1616,13 @@ mod tests { #[test] fn test_read_btf_type_struct() { let endianness = Endianness::default(); - 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, - ]; + 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); }); @@ -1662,10 +1631,13 @@ mod tests { #[test] fn test_read_btf_type_union() { let endianness = Endianness::default(); - 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, - ]; + 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); }); @@ -1674,10 +1646,11 @@ mod tests { #[test] fn test_read_btf_type_enum() { let endianness = Endianness::default(); - 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, - ]; + 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); }); @@ -1686,9 +1659,13 @@ mod tests { #[test] fn test_read_btf_type_fwd() { let endianness = Endianness::default(); - let data: &[u8] = &[ - 0x0b, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 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); }); @@ -1697,9 +1674,8 @@ mod tests { #[test] fn test_read_btf_type_typedef() { let endianness = Endianness::default(); - let data: &[u8] = &[ - 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0b, 0x00, 0x00, 0x00, - ]; + 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); }); @@ -1708,9 +1684,13 @@ mod tests { #[test] fn test_read_btf_type_volatile() { let endianness = Endianness::default(); - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x24, 0x00, 0x00, 0x00, - ]; + 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); }); @@ -1719,9 +1699,8 @@ mod tests { #[test] fn test_read_btf_type_const() { let endianness = Endianness::default(); - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x00, - ]; + 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); }); @@ -1730,9 +1709,13 @@ mod tests { #[test] fn test_read_btf_type_restrict() { let endianness = Endianness::default(); - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x04, 0x00, 0x00, 0x00, - ]; + 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); }); @@ -1741,9 +1724,8 @@ mod tests { #[test] fn test_read_btf_type_func() { let endianness = Endianness::default(); - let data: &[u8] = &[ - 0x17, 0x8b, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xf0, 0xe4, 0x00, 0x00, - ]; + 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); }); @@ -1752,10 +1734,12 @@ mod tests { #[test] fn test_read_btf_type_func_proto() { let endianness = Endianness::default(); - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, - ]; + 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); }); @@ -1765,10 +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 - let data: &[u8] = &[ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0xf0, 0x00, 0x00, 0x00, 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); }); @@ -1777,10 +1759,13 @@ mod tests { #[test] fn test_read_btf_type_func_datasec() { let endianness = Endianness::default(); - 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, - ]; + 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: _, @@ -1802,9 +1787,8 @@ mod tests { #[test] fn test_read_btf_type_float() { let endianness = Endianness::default(); - let data: &[u8] = &[ - 0x78, 0xfd, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x00, - ]; + 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); }); @@ -1856,15 +1840,9 @@ mod tests { #[test] pub fn test_read_btf_type_enum64() { let endianness = Endianness::default(); - 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 - ]; - + 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/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/aya-obj/src/obj.rs b/aya-obj/src/obj.rs index f6f4fc8b..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,22 +1595,32 @@ mod tests { #[test] fn sanitizes_empty_btf_files_to_none() { let mut obj = fake_obj(); - 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(); + + 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", - &[ - 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, - ], + &btf_ext_bytes, None, )) .unwrap(); @@ -2588,6 +2599,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 +2672,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)]; 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; 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};