Merge pull request #974 from Billy99/billy99-arch-ppc64-s390x

aya: add archs powerpc64 and s390x to aya
pull/1008/head
Alessandro Decina 3 weeks ago committed by GitHub
commit ab5e688fd4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -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"

@ -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

@ -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]

@ -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;

@ -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::<btf_header>(&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::<TestStruct>(&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::<BtfTestStruct>(&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::<btf_ext_header>(&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

@ -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;

@ -662,7 +662,8 @@ pub struct Union {
impl Union {
pub(crate) fn new(name_offset: u32, size: u32, members: Vec<BtfMember>) -> 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);
});

@ -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::*;

@ -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::<btf_ext_header>(&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();

@ -547,8 +547,17 @@ mod tests {
let offset = PAGE_SIZE - mem::size_of::<perf_event_header>() - 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::<u64>() as u32,
},
#[cfg(target_endian = "little")]
value: 0xCAFEBABEu32,
#[cfg(target_endian = "big")]
value: 0xBAADCAFEu32,
};
let offset = PAGE_SIZE - mem::size_of::<PerfSample<u32>>();
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)];

@ -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::<bpf_attr>() };
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::<bpf_attr>() };
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::<bpf_attr>() };
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::<bpf_attr>() };
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;

@ -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\"))");
}

@ -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::*;
}

@ -0,0 +1,3 @@
#![allow(clippy::all, dead_code)]
pub mod bindings;
pub mod helpers;

@ -0,0 +1,3 @@
#![allow(clippy::all, dead_code)]
pub mod bindings;
pub mod helpers;

@ -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\"))");
}

@ -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;
}

@ -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)");
}

@ -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<T> FromPtRegs for *const T {
}
}
#[cfg(bpf_target_arch = "powerpc64")]
impl<T> FromPtRegs for *const T {
fn from_argument(ctx: &pt_regs, n: usize) -> Option<Self> {
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<Self> {
unsafe { bpf_probe_read(&ctx.gpr[3]).map(|v| v as *const _).ok() }
}
}
#[cfg(bpf_target_arch = "s390x")]
impl<T> FromPtRegs for *const T {
fn from_argument(ctx: &pt_regs, n: usize) -> Option<Self> {
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<Self> {
unsafe { bpf_probe_read(&ctx.gprs[2]).map(|v| v as *const _).ok() }
}
}
#[cfg(bpf_target_arch = "x86_64")]
impl<T> FromPtRegs for *mut T {
fn from_argument(ctx: &pt_regs, n: usize) -> Option<Self> {
@ -238,6 +273,36 @@ impl<T> FromPtRegs for *mut T {
}
}
#[cfg(bpf_target_arch = "powerpc64")]
impl<T> FromPtRegs for *mut T {
fn from_argument(ctx: &pt_regs, n: usize) -> Option<Self> {
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<Self> {
unsafe { bpf_probe_read(&ctx.gpr[3]).map(|v| v as *mut _).ok() }
}
}
#[cfg(bpf_target_arch = "s390x")]
impl<T> FromPtRegs for *mut T {
fn from_argument(ctx: &pt_regs, n: usize) -> Option<Self> {
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<Self> {
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<Self> {
if n <= 7 {
Some(ctx.gpr[3 + n] as *const $type as _)
} else {
None
}
}
fn from_retval(ctx: &pt_regs) -> Option<Self> {
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<Self> {
if n <= 4 {
Some(ctx.gprs[2 + n] as *const $type as _)
} else {
None
}
}
fn from_retval(ctx: &pt_regs) -> Option<Self> {
Some(ctx.gprs[2] as *const $type as _)
}
}
};
}

@ -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};

@ -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};

Loading…
Cancel
Save