|
| 1 | +use aya_bpf_bindings::bindings::bpf_raw_tracepoint_args; |
| 2 | + |
1 | 3 | use crate::{cty::c_void, helpers::bpf_probe_read};
|
2 | 4 |
|
3 | 5 | // aarch64 uses user_pt_regs instead of pt_regs
|
@@ -326,3 +328,70 @@ impl_from_pt_regs!(i32);
|
326 | 328 | impl_from_pt_regs!(i64);
|
327 | 329 | impl_from_pt_regs!(usize);
|
328 | 330 | impl_from_pt_regs!(isize);
|
| 331 | + |
| 332 | +/// A Rust wrapper on `bpf_raw_tracepoint_args`. |
| 333 | +pub struct RawTracepointArgs { |
| 334 | + args: *mut bpf_raw_tracepoint_args, |
| 335 | +} |
| 336 | + |
| 337 | +impl RawTracepointArgs { |
| 338 | + pub fn new(args: *mut bpf_raw_tracepoint_args) -> Self { |
| 339 | + RawTracepointArgs { args } |
| 340 | + } |
| 341 | + |
| 342 | + /// Returns the n-th argument of the raw tracepoint. |
| 343 | + /// |
| 344 | + /// ## Safety |
| 345 | + /// |
| 346 | + /// This method is unsafe because it performs raw pointer conversion and makes assumptions |
| 347 | + /// about the structure of the `bpf_raw_tracepoint_args` type. The tracepoint arguments are |
| 348 | + /// represented as an array of `__u64` values (i.e., `__u64 args[0]`), and this method |
| 349 | + /// provides a way to access these arguments conveniently in Rust using `as_slice`. |
| 350 | + /// |
| 351 | + /// However, the method does not check the total number of available arguments for a given |
| 352 | + /// tracepoint and assumes that the slice has at least `n` elements, leading to undefined |
| 353 | + /// behavior if this condition is not met. |
| 354 | + pub unsafe fn arg<T: FromRawTracepointArgs>(&self, n: usize) -> *const T { |
| 355 | + &T::from_argument(&*self.args, n) |
| 356 | + } |
| 357 | +} |
| 358 | + |
| 359 | +pub unsafe trait FromRawTracepointArgs: Sized { |
| 360 | + unsafe fn from_argument(ctx: &bpf_raw_tracepoint_args, n: usize) -> Self; |
| 361 | +} |
| 362 | + |
| 363 | +unsafe impl<T> FromRawTracepointArgs for *const T { |
| 364 | + unsafe fn from_argument(ctx: &bpf_raw_tracepoint_args, n: usize) -> *const T { |
| 365 | + // Raw tracepoint arguments are exposed as `__u64 args[0]`. |
| 366 | + // https://elixir.bootlin.com/linux/v6.5.5/source/include/uapi/linux/bpf.h#L6829 |
| 367 | + // |
| 368 | + // The most convenient way of accessing such type in Rust is to use |
| 369 | + // `as_slice`. |
| 370 | + // |
| 371 | + // We don't know how many arguments are there for the given tracepoint, |
| 372 | + // so we just assume that the slice has at least n elements. The whole |
| 373 | + // assumntion and implementation is unsafe. |
| 374 | + ctx.args.as_slice(n + 1)[n] as *const _ |
| 375 | + } |
| 376 | +} |
| 377 | + |
| 378 | +macro_rules! unsafe_impl_from_raw_tracepoint_args { |
| 379 | + ($type:ident) => { |
| 380 | + unsafe impl FromRawTracepointArgs for $type { |
| 381 | + unsafe fn from_argument(ctx: &bpf_raw_tracepoint_args, n: usize) -> Self { |
| 382 | + ctx.args.as_slice(n + 1)[n] as _ |
| 383 | + } |
| 384 | + } |
| 385 | + }; |
| 386 | +} |
| 387 | + |
| 388 | +unsafe_impl_from_raw_tracepoint_args!(u8); |
| 389 | +unsafe_impl_from_raw_tracepoint_args!(u16); |
| 390 | +unsafe_impl_from_raw_tracepoint_args!(u32); |
| 391 | +unsafe_impl_from_raw_tracepoint_args!(u64); |
| 392 | +unsafe_impl_from_raw_tracepoint_args!(i8); |
| 393 | +unsafe_impl_from_raw_tracepoint_args!(i16); |
| 394 | +unsafe_impl_from_raw_tracepoint_args!(i32); |
| 395 | +unsafe_impl_from_raw_tracepoint_args!(i64); |
| 396 | +unsafe_impl_from_raw_tracepoint_args!(usize); |
| 397 | +unsafe_impl_from_raw_tracepoint_args!(isize); |
0 commit comments