Merge pull request #711 from dave-tucker/sleepable

Tidy up aya-bpf-macros (again)
reviewable/pr638/r15
Dave Tucker 1 year ago committed by GitHub
commit 77e9603976
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,28 +1,39 @@
use syn::{ use syn::{
parse::{Parse, ParseStream}, parse::{Parse, ParseStream},
punctuated::{Pair, Punctuated}, punctuated::{Pair, Punctuated},
token::Eq,
Error, Ident, LitStr, Result, Token, Error, Ident, LitStr, Result, Token,
}; };
pub(crate) struct NameValue { pub(crate) struct NameValue {
name: Ident, name: Ident,
_eq: Eq,
value: LitStr, value: LitStr,
} }
pub(crate) enum Arg {
String(NameValue),
Bool(Ident),
}
pub(crate) struct Args { pub(crate) struct Args {
pub(crate) args: Vec<NameValue>, pub(crate) args: Vec<Arg>,
} }
impl Parse for Args { impl Parse for Args {
fn parse(input: ParseStream) -> Result<Args> { fn parse(input: ParseStream) -> Result<Args> {
let args = Punctuated::<NameValue, Token![,]>::parse_terminated_with(input, |input| { let args = Punctuated::<Arg, Token![,]>::parse_terminated_with(input, |input| {
Ok(NameValue { let ident = input.parse::<Ident>()?;
name: input.parse()?, let lookahead = input.lookahead1();
_eq: input.parse()?, if input.is_empty() || lookahead.peek(Token![,]) {
value: input.parse()?, Ok(Arg::Bool(ident))
}) } else if lookahead.peek(Token![=]) {
let _: Token![=] = input.parse()?;
Ok(Arg::String(NameValue {
name: ident,
value: input.parse()?,
}))
} else {
Err(lookahead.error())
}
})? })?
.into_pairs() .into_pairs()
.map(|pair| match pair { .map(|pair| match pair {
@ -35,35 +46,38 @@ impl Parse for Args {
} }
} }
pub(crate) fn pop_arg(args: &mut Args, name: &str) -> Option<String> { pub(crate) fn pop_string_arg(args: &mut Args, name: &str) -> Option<String> {
match args.args.iter().position(|arg| arg.name == name) { args.args
Some(index) => Some(args.args.remove(index).value.value()), .iter()
None => None, .position(|arg| matches!(arg, Arg::String(name_val) if name_val.name == name))
} .map(|index| match args.args.remove(index) {
Arg::String(v) => v.value.value(),
_ => panic!("impossible variant"),
})
} }
pub(crate) fn pop_required_arg(args: &mut Args, name: &str) -> Result<String> { pub(crate) fn pop_bool_arg(args: &mut Args, name: &str) -> bool {
let value = match args.args.iter().position(|arg| arg.name == name) { args.args
Some(index) => Some(args.args.remove(index).value.value()), .iter()
None => None, .position(|arg| matches!(arg, Arg::Bool(ident) if ident == name))
}; .map(|index| match args.args.remove(index) {
match value { Arg::Bool(ident) => ident,
Some(value) => Ok(value), _ => panic!("impossible variant"),
None => Err(Error::new_spanned( })
args.args.first().unwrap().name.clone(), .is_some()
format!("missing required argument `{}`", name),
)),
}
} }
pub(crate) fn err_on_unknown_args(args: &Args) -> Result<()> { pub(crate) fn err_on_unknown_args(args: &Args) -> Result<()> {
if let Some(arg) = args.args.get(0) { if let Some(arg) = args.args.get(0) {
return Err(Error::new_spanned(&arg.name, "invalid argument")); let tokens = match arg {
Arg::String(name_val) => name_val.name.clone(),
Arg::Bool(ident) => ident.clone(),
};
return Err(Error::new_spanned(tokens, "invalid argument"));
} }
Ok(()) Ok(())
} }
pub(crate) fn name_arg(args: &mut Args) -> Result<Option<String>> { pub(crate) fn name_arg(args: &mut Args) -> Option<String> {
let name = pop_arg(args, "name"); pop_string_arg(args, "name")
Ok(name)
} }

@ -2,43 +2,31 @@ use std::borrow::Cow;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use quote::quote; use quote::quote;
use syn::{Error, ItemFn, Result}; use syn::{ItemFn, Result};
use crate::args::{err_on_unknown_args, pop_arg, pop_required_arg, Args}; use crate::args::{err_on_unknown_args, pop_string_arg, Args};
pub(crate) struct BtfTracePoint { pub(crate) struct BtfTracePoint {
item: ItemFn, item: ItemFn,
function: String, function: Option<String>,
sleepable: bool,
} }
impl BtfTracePoint { impl BtfTracePoint {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self> {
let mut args: Args = syn::parse2(attrs)?;
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
let function = pop_required_arg(&mut args, "function")?; let mut args: Args = syn::parse2(attrs)?;
let mut sleepable = false; let function = pop_string_arg(&mut args, "function");
if let Some(s) = pop_arg(&mut args, "sleepable") {
if let Ok(m) = s.parse() {
sleepable = m
} else {
return Err(Error::new_spanned(
s,
"invalid value. should be 'true' or 'false'",
));
}
}
err_on_unknown_args(&args)?; err_on_unknown_args(&args)?;
Ok(BtfTracePoint {
item, Ok(BtfTracePoint { item, function })
function,
sleepable,
})
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> Result<TokenStream> {
let section_prefix = if self.sleepable { "tp_btf.s" } else { "tp_btf" }; let section_name: Cow<'_, _> = if let Some(function) = &self.function {
let section_name: Cow<'_, _> = format!("{}/{}", section_prefix, self.function).into(); format!("tp_btf/{}", function).into()
} else {
"tp_btf".into()
};
let fn_vis = &self.item.vis; let fn_vis = &self.item.vis;
let fn_name = self.item.sig.ident.clone(); let fn_name = self.item.sig.ident.clone();
let item = &self.item; let item = &self.item;
@ -62,6 +50,33 @@ mod tests {
#[test] #[test]
fn test_btf_tracepoint() { fn test_btf_tracepoint() {
let prog = BtfTracePoint::parse(
parse_quote!(),
parse_quote!(
fn foo(ctx: BtfTracePointContext) -> i32 {
0
}
),
)
.unwrap();
let expanded = prog.expand().unwrap();
let expected = quote!(
#[no_mangle]
#[link_section = "tp_btf"]
fn foo(ctx: *mut ::core::ffi::c_void) -> i32 {
let _ = foo(::aya_bpf::programs::BtfTracePointContext::new(ctx));
return 0;
fn foo(ctx: BtfTracePointContext) -> i32 {
0
}
}
);
assert_eq!(expected.to_string(), expanded.to_string());
}
#[test]
fn test_btf_tracepoint_with_function() {
let prog = BtfTracePoint::parse( let prog = BtfTracePoint::parse(
parse_quote!(function = "some_func"), parse_quote!(function = "some_func"),
parse_quote!( parse_quote!(

@ -18,11 +18,10 @@ impl CgroupSkb {
let ident: Ident = syn::parse2(attrs)?; let ident: Ident = syn::parse2(attrs)?;
match ident.to_string().as_str() { match ident.to_string().as_str() {
"ingress" | "egress" => (), "ingress" | "egress" => (),
_ => abort!(attach_type, "invalid attach type"), _ => abort!(ident, "invalid attach type"),
} }
attach_type = Some(ident.to_string()); attach_type = Some(ident.to_string());
} }
Ok(CgroupSkb { item, attach_type }) Ok(CgroupSkb { item, attach_type })
} }

@ -12,6 +12,9 @@ pub(crate) struct CgroupSock {
impl CgroupSock { impl CgroupSock {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<CgroupSock> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<CgroupSock> {
if attrs.is_empty() {
abort!(attrs, "missing attach type")
}
let item: ItemFn = syn::parse2(item)?; let item: ItemFn = syn::parse2(item)?;
let attach_type: Ident = syn::parse2(attrs)?; let attach_type: Ident = syn::parse2(attrs)?;
match attach_type.to_string().as_str() { match attach_type.to_string().as_str() {

@ -15,6 +15,7 @@ impl CgroupSockAddr {
if attrs.is_empty() { if attrs.is_empty() {
abort!(attrs, "missing attach type") abort!(attrs, "missing attach type")
} }
let item = syn::parse2(item)?;
let attach_type: Ident = syn::parse2(attrs)?; let attach_type: Ident = syn::parse2(attrs)?;
match attach_type.to_string().as_str() { match attach_type.to_string().as_str() {
"connect4" | "connect6" | "bind4" | "bind6" | "getpeername4" | "getpeername6" "connect4" | "connect6" | "bind4" | "bind6" | "getpeername4" | "getpeername6"
@ -22,7 +23,6 @@ impl CgroupSockAddr {
| "recvmsg6" => (), | "recvmsg6" => (),
_ => abort!(attach_type, "invalid attach type"), _ => abort!(attach_type, "invalid attach type"),
} }
let item = syn::parse2(item)?;
Ok(CgroupSockAddr { Ok(CgroupSockAddr {
item, item,
attach_type: attach_type.to_string(), attach_type: attach_type.to_string(),

@ -15,12 +15,12 @@ impl CgroupSockopt {
if attrs.is_empty() { if attrs.is_empty() {
abort!(attrs, "expected attach type"); abort!(attrs, "expected attach type");
} }
let item = syn::parse2(item)?;
let attach_type: Ident = syn::parse2(attrs)?; let attach_type: Ident = syn::parse2(attrs)?;
match attach_type.to_string().as_str() { match attach_type.to_string().as_str() {
"getsockopt" | "setsockopt" => (), "getsockopt" | "setsockopt" => (),
_ => abort!(attach_type, "invalid attach type"), _ => abort!(attach_type, "invalid attach type"),
} }
let item = syn::parse2(item)?;
Ok(CgroupSockopt { Ok(CgroupSockopt {
item, item,
attach_type: attach_type.to_string(), attach_type: attach_type.to_string(),

@ -1,37 +1,38 @@
use std::borrow::Cow; use std::borrow::Cow;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use proc_macro_error::abort;
use quote::quote; use quote::quote;
use syn::{ItemFn, Result}; use syn::{ItemFn, Result};
use crate::args::{err_on_unknown_args, pop_required_arg}; use crate::args::{err_on_unknown_args, pop_bool_arg, pop_string_arg};
pub(crate) struct FEntry { pub(crate) struct FEntry {
item: ItemFn, item: ItemFn,
function: String, function: Option<String>,
sleepable: bool, sleepable: bool,
} }
impl FEntry { impl FEntry {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<FEntry> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<FEntry> {
if attrs.is_empty() {
abort!(attrs, "missing function name");
}
let mut args = syn::parse2(attrs)?;
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
let function = pop_required_arg(&mut args, "function")?; let mut args = syn::parse2(attrs)?;
let function = pop_string_arg(&mut args, "function");
let sleepable = pop_bool_arg(&mut args, "sleepable");
err_on_unknown_args(&args)?; err_on_unknown_args(&args)?;
Ok(FEntry { Ok(FEntry {
item, item,
function, function,
sleepable: false, sleepable,
}) })
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> Result<TokenStream> {
let section_prefix = if self.sleepable { "fentry.s" } else { "fentry" }; let section_prefix = if self.sleepable { "fentry.s" } else { "fentry" };
let section_name: Cow<'_, _> = format!("{}/{}", section_prefix, self.function).into(); let section_name: Cow<'_, _> = if let Some(function) = &self.function {
format!("{}/{}", section_prefix, function).into()
} else {
section_prefix.into()
};
let fn_vis = &self.item.vis; let fn_vis = &self.item.vis;
let fn_name = self.item.sig.ident.clone(); let fn_name = self.item.sig.ident.clone();
let item = &self.item; let item = &self.item;
@ -55,6 +56,33 @@ mod tests {
#[test] #[test]
fn test_fentry() { fn test_fentry() {
let prog = FEntry::parse(
parse_quote! {},
parse_quote! {
fn sys_clone(ctx: &mut aya_bpf::programs::FEntryContext) -> i32 {
0
}
},
)
.unwrap();
let expanded = prog.expand().unwrap();
let expected = quote! {
#[no_mangle]
#[link_section = "fentry"]
fn sys_clone(ctx: *mut ::core::ffi::c_void) -> i32 {
let _ = sys_clone(::aya_bpf::programs::FEntryContext::new(ctx));
return 0;
fn sys_clone(ctx: &mut aya_bpf::programs::FEntryContext) -> i32 {
0
}
}
};
assert_eq!(expected.to_string(), expanded.to_string());
}
#[test]
fn test_fentry_with_function() {
let prog = FEntry::parse( let prog = FEntry::parse(
parse_quote! { parse_quote! {
function = "sys_clone" function = "sys_clone"
@ -81,4 +109,33 @@ mod tests {
}; };
assert_eq!(expected.to_string(), expanded.to_string()); assert_eq!(expected.to_string(), expanded.to_string());
} }
#[test]
fn test_fentry_sleepable() {
let prog = FEntry::parse(
parse_quote! {
sleepable
},
parse_quote! {
fn sys_clone(ctx: &mut aya_bpf::programs::FEntryContext) -> i32 {
0
}
},
)
.unwrap();
let expanded = prog.expand().unwrap();
let expected = quote! {
#[no_mangle]
#[link_section = "fentry.s"]
fn sys_clone(ctx: *mut ::core::ffi::c_void) -> i32 {
let _ = sys_clone(::aya_bpf::programs::FEntryContext::new(ctx));
return 0;
fn sys_clone(ctx: &mut aya_bpf::programs::FEntryContext) -> i32 {
0
}
}
};
assert_eq!(expected.to_string(), expanded.to_string());
}
} }

@ -1,37 +1,38 @@
use std::borrow::Cow; use std::borrow::Cow;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use proc_macro_error::abort;
use quote::quote; use quote::quote;
use syn::{ItemFn, Result}; use syn::{ItemFn, Result};
use crate::args::{err_on_unknown_args, pop_required_arg}; use crate::args::{err_on_unknown_args, pop_bool_arg, pop_string_arg};
pub(crate) struct FExit { pub(crate) struct FExit {
item: ItemFn, item: ItemFn,
function: String, function: Option<String>,
sleepable: bool, sleepable: bool,
} }
impl FExit { impl FExit {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<FExit> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<FExit> {
if attrs.is_empty() {
abort!(attrs, "missing function name");
}
let mut args = syn::parse2(attrs)?;
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
let function = pop_required_arg(&mut args, "function")?; let mut args = syn::parse2(attrs)?;
let function = pop_string_arg(&mut args, "function");
let sleepable = pop_bool_arg(&mut args, "sleepable");
err_on_unknown_args(&args)?; err_on_unknown_args(&args)?;
Ok(FExit { Ok(FExit {
item, item,
function, function,
sleepable: false, sleepable,
}) })
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> Result<TokenStream> {
let section_prefix = if self.sleepable { "fexit.s" } else { "fexit" }; let section_prefix = if self.sleepable { "fexit.s" } else { "fexit" };
let section_name: Cow<'_, _> = format!("{}/{}", section_prefix, self.function).into(); let section_name: Cow<'_, _> = if let Some(function) = &self.function {
format!("{}/{}", section_prefix, function).into()
} else {
section_prefix.into()
};
let fn_vis = &self.item.vis; let fn_vis = &self.item.vis;
let fn_name = self.item.sig.ident.clone(); let fn_name = self.item.sig.ident.clone();
let item = &self.item; let item = &self.item;
@ -55,6 +56,33 @@ mod tests {
#[test] #[test]
fn test_fexit() { fn test_fexit() {
let prog = FExit::parse(
parse_quote! {},
parse_quote! {
fn sys_clone(ctx: &mut FExitContext) -> i32 {
0
}
},
)
.unwrap();
let expanded = prog.expand().unwrap();
let expected = quote! {
#[no_mangle]
#[link_section = "fexit"]
fn sys_clone(ctx: *mut ::core::ffi::c_void) -> i32 {
let _ = sys_clone(::aya_bpf::programs::FExitContext::new(ctx));
return 0;
fn sys_clone(ctx: &mut FExitContext) -> i32 {
0
}
}
};
assert_eq!(expected.to_string(), expanded.to_string());
}
#[test]
fn test_fexit_with_function() {
let prog = FExit::parse( let prog = FExit::parse(
parse_quote! { parse_quote! {
function = "sys_clone" function = "sys_clone"
@ -81,4 +109,33 @@ mod tests {
}; };
assert_eq!(expected.to_string(), expanded.to_string()); assert_eq!(expected.to_string(), expanded.to_string());
} }
#[test]
fn test_fexit_sleepable() {
let prog = FExit::parse(
parse_quote! {
function = "sys_clone", sleepable
},
parse_quote! {
fn sys_clone(ctx: &mut FExitContext) -> i32 {
0
}
},
)
.unwrap();
let expanded = prog.expand().unwrap();
let expected = quote! {
#[no_mangle]
#[link_section = "fexit.s/sys_clone"]
fn sys_clone(ctx: *mut ::core::ffi::c_void) -> i32 {
let _ = sys_clone(::aya_bpf::programs::FExitContext::new(ctx));
return 0;
fn sys_clone(ctx: &mut FExitContext) -> i32 {
0
}
}
};
assert_eq!(expected.to_string(), expanded.to_string());
}
} }

@ -5,7 +5,7 @@ use proc_macro2::TokenStream;
use quote::quote; use quote::quote;
use syn::{ItemFn, Result}; use syn::{ItemFn, Result};
use crate::args::{err_on_unknown_args, pop_arg}; use crate::args::{err_on_unknown_args, pop_string_arg};
#[allow(clippy::enum_variant_names)] #[allow(clippy::enum_variant_names)]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
@ -33,16 +33,12 @@ pub(crate) struct KProbe {
impl KProbe { impl KProbe {
pub(crate) fn parse(kind: KProbeKind, attrs: TokenStream, item: TokenStream) -> Result<KProbe> { pub(crate) fn parse(kind: KProbeKind, attrs: TokenStream, item: TokenStream) -> Result<KProbe> {
let mut function = None;
let mut offset = None;
if !attrs.is_empty() {
let mut args = syn::parse2(attrs)?;
function = pop_arg(&mut args, "function");
offset = pop_arg(&mut args, "offset").map(|v| v.parse::<u64>().unwrap());
err_on_unknown_args(&args)?;
}
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
let mut args = syn::parse2(attrs)?;
let function = pop_string_arg(&mut args, "function");
let offset = pop_string_arg(&mut args, "offset").map(|v| v.parse::<u64>().unwrap());
err_on_unknown_args(&args)?;
Ok(KProbe { Ok(KProbe {
kind, kind,
item, item,

@ -309,7 +309,7 @@ pub fn raw_tracepoint(attrs: TokenStream, item: TokenStream) -> TokenStream {
/// Used to implement security policy and audit logging. /// Used to implement security policy and audit logging.
/// ///
/// The hook name is the first argument to the macro. /// The hook name is the first argument to the macro.
/// You may also provide `sleepable = true` to mark the program as sleepable. /// You may also provide `sleepable` to mark the program as sleepable.
/// Arguments should be comma separated. /// Arguments should be comma separated.
/// ///
/// LSM probes can be attached to the kernel's security hooks to implement mandatory /// LSM probes can be attached to the kernel's security hooks to implement mandatory

@ -1,37 +1,38 @@
use std::borrow::Cow; use std::borrow::Cow;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use proc_macro_error::abort;
use quote::quote; use quote::quote;
use syn::{ItemFn, Result}; use syn::{ItemFn, Result};
use crate::args::err_on_unknown_args; use crate::args::{err_on_unknown_args, pop_bool_arg, pop_string_arg};
pub(crate) struct Lsm { pub(crate) struct Lsm {
item: ItemFn, item: ItemFn,
hook: String, hook: Option<String>,
sleepable: bool, sleepable: bool,
} }
impl Lsm { impl Lsm {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Lsm> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Lsm> {
if attrs.is_empty() {
abort!(attrs, "missing hook name");
}
let mut args = syn::parse2(attrs)?;
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
let hook = crate::args::pop_required_arg(&mut args, "hook")?; let mut args = syn::parse2(attrs)?;
let hook = pop_string_arg(&mut args, "hook");
let sleepable = pop_bool_arg(&mut args, "sleepable");
err_on_unknown_args(&args)?; err_on_unknown_args(&args)?;
Ok(Lsm { Ok(Lsm {
item, item,
hook, hook,
sleepable: false, sleepable,
}) })
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> Result<TokenStream> {
let section_prefix = if self.sleepable { "lsm.s" } else { "lsm" }; let section_prefix = if self.sleepable { "lsm.s" } else { "lsm" };
let section_name: Cow<'_, _> = format!("{}/{}", section_prefix, self.hook).into(); let section_name: Cow<'_, _> = if let Some(hook) = &self.hook {
format!("{}/{}", section_prefix, hook).into()
} else {
section_prefix.into()
};
let fn_vis = &self.item.vis; let fn_vis = &self.item.vis;
let fn_name = self.item.sig.ident.clone(); let fn_name = self.item.sig.ident.clone();
let item = &self.item; let item = &self.item;
@ -55,6 +56,35 @@ mod tests {
use super::*; use super::*;
use syn::parse_quote; use syn::parse_quote;
#[test]
fn test_lsm_sleepable() {
let prog = Lsm::parse(
parse_quote! {
sleepable,
hook = "bprm_committed_creds"
},
parse_quote! {
fn bprm_committed_creds(ctx: &mut ::aya_bpf::programs::LsmContext) -> i32 {
0
}
},
)
.unwrap();
let expanded = prog.expand().unwrap();
let expected = quote! {
#[no_mangle]
#[link_section = "lsm.s/bprm_committed_creds"]
fn bprm_committed_creds(ctx: *mut ::core::ffi::c_void) -> i32 {
return bprm_committed_creds(::aya_bpf::programs::LsmContext::new(ctx));
fn bprm_committed_creds(ctx: &mut ::aya_bpf::programs::LsmContext) -> i32 {
0
}
}
};
assert_eq!(expected.to_string(), expanded.to_string());
}
#[test] #[test]
fn test_lsm() { fn test_lsm() {
let prog = Lsm::parse( let prog = Lsm::parse(

@ -14,9 +14,9 @@ pub(crate) struct Map {
impl Map { impl Map {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Map> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Map> {
let mut args = syn::parse2(attrs)?;
let item: ItemStatic = syn::parse2(item)?; let item: ItemStatic = syn::parse2(item)?;
let name = name_arg(&mut args)?.unwrap_or_else(|| item.ident.to_string()); let mut args = syn::parse2(attrs)?;
let name = name_arg(&mut args).unwrap_or_else(|| item.ident.to_string());
Ok(Map { item, name }) Ok(Map { item, name })
} }

@ -1,31 +1,32 @@
use std::borrow::Cow; use std::borrow::Cow;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use proc_macro_error::abort;
use quote::quote; use quote::quote;
use syn::{ItemFn, Result}; use syn::{ItemFn, Result};
use crate::args::{err_on_unknown_args, pop_required_arg}; use crate::args::{err_on_unknown_args, pop_string_arg};
pub(crate) struct RawTracePoint { pub(crate) struct RawTracePoint {
item: ItemFn, item: ItemFn,
tracepoint: String, tracepoint: Option<String>,
} }
impl RawTracePoint { impl RawTracePoint {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<RawTracePoint> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<RawTracePoint> {
if attrs.is_empty() {
abort!(attrs, "expected `tracepoint` attribute")
}
let mut args = syn::parse2(attrs)?;
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
let tracepoint = pop_required_arg(&mut args, "tracepoint")?; let mut args = syn::parse2(attrs)?;
let tracepoint = pop_string_arg(&mut args, "tracepoint");
err_on_unknown_args(&args)?; err_on_unknown_args(&args)?;
Ok(RawTracePoint { item, tracepoint }) Ok(RawTracePoint { item, tracepoint })
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> Result<TokenStream> {
let section_name: Cow<'_, _> = format!("raw_tp/{}", self.tracepoint).into(); let section_name: Cow<'_, _> = if let Some(tracepoint) = &self.tracepoint {
format!("raw_tp/{}", tracepoint).into()
} else {
"raw_tp".into()
};
let fn_vis = &self.item.vis; let fn_vis = &self.item.vis;
let fn_name = self.item.sig.ident.clone(); let fn_name = self.item.sig.ident.clone();
let item = &self.item; let item = &self.item;

@ -5,7 +5,7 @@ use proc_macro_error::abort;
use quote::quote; use quote::quote;
use syn::{ItemFn, Result}; use syn::{ItemFn, Result};
use crate::args::{err_on_unknown_args, pop_arg}; use crate::args::{err_on_unknown_args, pop_string_arg};
pub(crate) struct TracePoint { pub(crate) struct TracePoint {
item: ItemFn, item: ItemFn,
@ -15,10 +15,10 @@ pub(crate) struct TracePoint {
impl TracePoint { impl TracePoint {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<TracePoint> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<TracePoint> {
let mut args = syn::parse2(attrs)?;
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
let name = pop_arg(&mut args, "name"); let mut args = syn::parse2(attrs)?;
let category = pop_arg(&mut args, "category"); let name = pop_string_arg(&mut args, "name");
let category = pop_string_arg(&mut args, "category");
err_on_unknown_args(&args)?; err_on_unknown_args(&args)?;
Ok(TracePoint { Ok(TracePoint {
item, item,

@ -5,7 +5,7 @@ use proc_macro_error::abort;
use quote::quote; use quote::quote;
use syn::{ItemFn, Result}; use syn::{ItemFn, Result};
use crate::args::{err_on_unknown_args, pop_arg}; use crate::args::{err_on_unknown_args, pop_bool_arg, pop_string_arg};
#[allow(clippy::enum_variant_names)] #[allow(clippy::enum_variant_names)]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
@ -30,32 +30,34 @@ pub(crate) struct UProbe {
function: Option<String>, function: Option<String>,
offset: Option<u64>, offset: Option<u64>,
item: ItemFn, item: ItemFn,
sleepable: bool,
} }
impl UProbe { impl UProbe {
pub(crate) fn parse(kind: UProbeKind, attrs: TokenStream, item: TokenStream) -> Result<UProbe> { pub(crate) fn parse(kind: UProbeKind, attrs: TokenStream, item: TokenStream) -> Result<UProbe> {
let mut path = None;
let mut function = None;
let mut offset = None;
if !attrs.is_empty() {
let mut args = syn::parse2(attrs)?;
path = pop_arg(&mut args, "path");
function = pop_arg(&mut args, "function");
offset = pop_arg(&mut args, "offset").map(|v| v.parse::<u64>().unwrap());
err_on_unknown_args(&args)?;
}
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
let mut args = syn::parse2(attrs)?;
let path = pop_string_arg(&mut args, "path");
let function = pop_string_arg(&mut args, "function");
let offset = pop_string_arg(&mut args, "offset").map(|v| v.parse::<u64>().unwrap());
let sleepable = pop_bool_arg(&mut args, "sleepable");
err_on_unknown_args(&args)?;
Ok(UProbe { Ok(UProbe {
kind, kind,
item, item,
path, path,
function, function,
offset, offset,
sleepable,
}) })
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> Result<TokenStream> {
let prefix = if self.sleepable {
format!("{}.s", self.kind)
} else {
format!("{}", self.kind)
};
let section_name: Cow<'_, _> = if self.path.is_some() && self.offset.is_some() { let section_name: Cow<'_, _> = if self.path.is_some() && self.offset.is_some() {
if self.function.is_none() { if self.function.is_none() {
abort!(self.item.sig.ident, "expected `function` attribute"); abort!(self.item.sig.ident, "expected `function` attribute");
@ -66,7 +68,7 @@ impl UProbe {
} }
format!( format!(
"{}/{}:{}+{}", "{}/{}:{}+{}",
self.kind, prefix,
path, path,
self.function.as_ref().unwrap(), self.function.as_ref().unwrap(),
self.offset.unwrap() self.offset.unwrap()
@ -80,9 +82,9 @@ impl UProbe {
if path.starts_with('/') { if path.starts_with('/') {
path.remove(0); path.remove(0);
} }
format!("{}/{}:{}", self.kind, path, self.function.as_ref().unwrap()).into() format!("{}/{}:{}", prefix, path, self.function.as_ref().unwrap()).into()
} else { } else {
format!("{}", self.kind).into() prefix.to_string().into()
}; };
let fn_vis = &self.item.vis; let fn_vis = &self.item.vis;
let fn_name = self.item.sig.ident.clone(); let fn_name = self.item.sig.ident.clone();
@ -135,6 +137,36 @@ mod tests {
); );
} }
#[test]
fn uprobe_sleepable() {
let uprobe = UProbe::parse(
UProbeKind::UProbe,
parse_quote! {sleepable},
parse_quote! {
fn foo(ctx: ProbeContext) -> u32 {
0
}
},
)
.unwrap();
assert_eq!(
uprobe.expand().unwrap().to_string(),
quote! {
#[no_mangle]
#[link_section = "uprobe.s"]
fn foo(ctx: *mut ::core::ffi::c_void) -> u32 {
let _ = foo(::aya_bpf::programs::ProbeContext::new(ctx));
return 0;
fn foo(ctx: ProbeContext) -> u32 {
0
}
}
}
.to_string()
);
}
#[test] #[test]
fn uprobe_with_path() { fn uprobe_with_path() {
let uprobe = UProbe::parse( let uprobe = UProbe::parse(

@ -1,9 +1,10 @@
use std::borrow::Cow; use std::borrow::Cow;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use proc_macro_error::abort;
use quote::quote; use quote::quote;
use syn::{Ident, ItemFn, Result}; use syn::{ItemFn, Result};
use crate::args::{err_on_unknown_args, pop_bool_arg, Args};
pub(crate) struct Xdp { pub(crate) struct Xdp {
item: ItemFn, item: ItemFn,
@ -12,15 +13,10 @@ pub(crate) struct Xdp {
impl Xdp { impl Xdp {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Xdp> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Xdp> {
let mut frags = false;
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
if !attrs.is_empty() { let mut args: Args = syn::parse2(attrs)?;
let ident: Ident = syn::parse2(attrs)?; let frags = pop_bool_arg(&mut args, "frags");
if ident != "frags" { err_on_unknown_args(&args)?;
abort!(ident, "unexpected attribute");
}
frags = true;
}
Ok(Xdp { item, frags }) Ok(Xdp { item, frags })
} }

@ -222,7 +222,6 @@ pub struct Function {
/// Currently, the following section names are not supported yet: /// Currently, the following section names are not supported yet:
/// - `flow_dissector`: `BPF_PROG_TYPE_FLOW_DISSECTOR` /// - `flow_dissector`: `BPF_PROG_TYPE_FLOW_DISSECTOR`
/// - `ksyscall+` or `kretsyscall+` /// - `ksyscall+` or `kretsyscall+`
/// - `uprobe.s+` or `uretprobe.s+`
/// - `usdt+` /// - `usdt+`
/// - `kprobe.multi+` or `kretprobe.multi+`: `BPF_TRACE_KPROBE_MULTI` /// - `kprobe.multi+` or `kretprobe.multi+`: `BPF_TRACE_KPROBE_MULTI`
/// - `lsm_cgroup+` /// - `lsm_cgroup+`
@ -233,7 +232,6 @@ pub struct Function {
/// - `syscall` /// - `syscall`
/// - `struct_ops+` /// - `struct_ops+`
/// - `fmod_ret+`, `fmod_ret.s+` /// - `fmod_ret+`, `fmod_ret.s+`
/// - `fentry.s+`, `fexit.s+`
/// - `iter+`, `iter.s+` /// - `iter+`, `iter.s+`
/// - `xdp.frags/cpumap`, `xdp/cpumap` /// - `xdp.frags/cpumap`, `xdp/cpumap`
/// - `xdp.frags/devmap`, `xdp/devmap` /// - `xdp.frags/devmap`, `xdp/devmap`
@ -248,9 +246,11 @@ pub enum ProgramSection {
}, },
UProbe { UProbe {
name: String, name: String,
sleepable: bool,
}, },
URetProbe { URetProbe {
name: String, name: String,
sleepable: bool,
}, },
TracePoint { TracePoint {
name: String, name: String,
@ -315,9 +315,11 @@ pub enum ProgramSection {
}, },
FEntry { FEntry {
name: String, name: String,
sleepable: bool,
}, },
FExit { FExit {
name: String, name: String,
sleepable: bool,
}, },
Extension { Extension {
name: String, name: String,
@ -340,8 +342,8 @@ impl ProgramSection {
match self { match self {
ProgramSection::KRetProbe { name } => name, ProgramSection::KRetProbe { name } => name,
ProgramSection::KProbe { name } => name, ProgramSection::KProbe { name } => name,
ProgramSection::UProbe { name } => name, ProgramSection::UProbe { name, .. } => name,
ProgramSection::URetProbe { name } => name, ProgramSection::URetProbe { name, .. } => name,
ProgramSection::TracePoint { name } => name, ProgramSection::TracePoint { name } => name,
ProgramSection::SocketFilter { name } => name, ProgramSection::SocketFilter { name } => name,
ProgramSection::Xdp { name, .. } => name, ProgramSection::Xdp { name, .. } => name,
@ -360,9 +362,9 @@ impl ProgramSection {
ProgramSection::PerfEvent { name } => name, ProgramSection::PerfEvent { name } => name,
ProgramSection::RawTracePoint { name } => name, ProgramSection::RawTracePoint { name } => name,
ProgramSection::Lsm { name, .. } => name, ProgramSection::Lsm { name, .. } => name,
ProgramSection::BtfTracePoint { name } => name, ProgramSection::BtfTracePoint { name, .. } => name,
ProgramSection::FEntry { name } => name, ProgramSection::FEntry { name, .. } => name,
ProgramSection::FExit { name } => name, ProgramSection::FExit { name, .. } => name,
ProgramSection::Extension { name } => name, ProgramSection::Extension { name } => name,
ProgramSection::SkLookup { name } => name, ProgramSection::SkLookup { name } => name,
ProgramSection::CgroupSock { name, .. } => name, ProgramSection::CgroupSock { name, .. } => name,
@ -388,8 +390,22 @@ impl FromStr for ProgramSection {
Ok(match kind { Ok(match kind {
"kprobe" => KProbe { name }, "kprobe" => KProbe { name },
"kretprobe" => KRetProbe { name }, "kretprobe" => KRetProbe { name },
"uprobe" => UProbe { name }, "uprobe" => UProbe {
"uretprobe" => URetProbe { name }, name,
sleepable: false,
},
"uprobe.s" => UProbe {
name,
sleepable: true,
},
"uretprobe" => URetProbe {
name,
sleepable: false,
},
"uretprobe.s" => URetProbe {
name,
sleepable: true,
},
"xdp" => Xdp { name, frags: false }, "xdp" => Xdp { name, frags: false },
"xdp.frags" => Xdp { name, frags: true }, "xdp.frags" => Xdp { name, frags: true },
"tp_btf" => BtfTracePoint { name }, "tp_btf" => BtfTracePoint { name },
@ -551,8 +567,22 @@ impl FromStr for ProgramSection {
name, name,
sleepable: true, sleepable: true,
}, },
"fentry" => FEntry { name }, "fentry" => FEntry {
"fexit" => FExit { name }, name,
sleepable: false,
},
"fentry.s" => FEntry {
name,
sleepable: true,
},
"fexit" => FExit {
name,
sleepable: false,
},
"fexit.s" => FExit {
name,
sleepable: true,
},
"freplace" => Extension { name }, "freplace" => Extension { name },
"sk_lookup" => SkLookup { name }, "sk_lookup" => SkLookup { name },
_ => { _ => {
@ -2018,6 +2048,81 @@ mod tests {
); );
} }
#[test]
fn test_parse_section_uprobe_sleepable() {
let mut obj = fake_obj();
fake_sym(&mut obj, 0, 0, "foo", FAKE_INS_LEN);
assert_matches!(
obj.parse_section(fake_section(
BpfSectionKind::Program,
"uprobe.s/foo",
bytes_of(&fake_ins()),
None
)),
Ok(())
);
assert_matches!(
obj.programs.get("foo"),
Some(Program {
section: ProgramSection::UProbe {
sleepable: true,
..
},
..
})
);
}
#[test]
fn test_parse_section_uretprobe() {
let mut obj = fake_obj();
fake_sym(&mut obj, 0, 0, "foo", FAKE_INS_LEN);
assert_matches!(
obj.parse_section(fake_section(
BpfSectionKind::Program,
"uretprobe/foo",
bytes_of(&fake_ins()),
None
)),
Ok(())
);
assert_matches!(
obj.programs.get("foo"),
Some(Program {
section: ProgramSection::URetProbe { .. },
..
})
);
}
#[test]
fn test_parse_section_uretprobe_sleepable() {
let mut obj = fake_obj();
fake_sym(&mut obj, 0, 0, "foo", FAKE_INS_LEN);
assert_matches!(
obj.parse_section(fake_section(
BpfSectionKind::Program,
"uretprobe.s/foo",
bytes_of(&fake_ins()),
None
)),
Ok(())
);
assert_matches!(
obj.programs.get("foo"),
Some(Program {
section: ProgramSection::URetProbe {
sleepable: true,
..
},
..
})
);
}
#[test] #[test]
fn test_parse_section_trace_point() { fn test_parse_section_trace_point() {
let mut obj = fake_obj(); let mut obj = fake_obj();
@ -2313,6 +2418,32 @@ mod tests {
); );
} }
#[test]
fn test_parse_section_fentry_sleepable() {
let mut obj = fake_obj();
fake_sym(&mut obj, 0, 0, "foo", FAKE_INS_LEN);
assert_matches!(
obj.parse_section(fake_section(
BpfSectionKind::Program,
"fentry.s/foo",
bytes_of(&fake_ins()),
None
)),
Ok(())
);
assert_matches!(
obj.programs.get("foo"),
Some(Program {
section: ProgramSection::FEntry {
sleepable: true,
..
},
..
})
);
}
#[test] #[test]
fn test_parse_section_fexit() { fn test_parse_section_fexit() {
let mut obj = fake_obj(); let mut obj = fake_obj();
@ -2336,6 +2467,32 @@ mod tests {
); );
} }
#[test]
fn test_parse_section_fexit_sleepable() {
let mut obj = fake_obj();
fake_sym(&mut obj, 0, 0, "foo", FAKE_INS_LEN);
assert_matches!(
obj.parse_section(fake_section(
BpfSectionKind::Program,
"fexit.s/foo",
bytes_of(&fake_ins()),
None
)),
Ok(())
);
assert_matches!(
obj.programs.get("foo"),
Some(Program {
section: ProgramSection::FExit {
sleepable: true,
..
},
..
})
);
}
#[test] #[test]
fn test_parse_section_cgroup_skb_ingress_unnamed() { fn test_parse_section_cgroup_skb_ingress_unnamed() {
let mut obj = fake_obj(); let mut obj = fake_obj();

@ -566,14 +566,28 @@ impl<'a> BpfLoader<'a> {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
kind: ProbeKind::KRetProbe, kind: ProbeKind::KRetProbe,
}), }),
ProgramSection::UProbe { .. } => Program::UProbe(UProbe { ProgramSection::UProbe { sleepable, name: _ } => {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), let mut data =
kind: ProbeKind::UProbe, ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level);
}), if *sleepable {
ProgramSection::URetProbe { .. } => Program::UProbe(UProbe { data.flags = BPF_F_SLEEPABLE;
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), }
kind: ProbeKind::URetProbe, Program::UProbe(UProbe {
}), data,
kind: ProbeKind::UProbe,
})
}
ProgramSection::URetProbe { sleepable, name: _ } => {
let mut data =
ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level);
if *sleepable {
data.flags = BPF_F_SLEEPABLE;
}
Program::UProbe(UProbe {
data,
kind: ProbeKind::URetProbe,
})
}
ProgramSection::TracePoint { .. } => Program::TracePoint(TracePoint { ProgramSection::TracePoint { .. } => Program::TracePoint(TracePoint {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
}), }),
@ -653,7 +667,7 @@ impl<'a> BpfLoader<'a> {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
}) })
} }
ProgramSection::Lsm { sleepable, .. } => { ProgramSection::Lsm { sleepable, name: _ } => {
let mut data = let mut data =
ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level); ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level);
if *sleepable { if *sleepable {
@ -666,12 +680,22 @@ impl<'a> BpfLoader<'a> {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
}) })
} }
ProgramSection::FEntry { .. } => Program::FEntry(FEntry { ProgramSection::FEntry { sleepable, name: _ } => {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), let mut data =
}), ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level);
ProgramSection::FExit { .. } => Program::FExit(FExit { if *sleepable {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), data.flags = BPF_F_SLEEPABLE;
}), }
Program::FEntry(FEntry { data })
}
ProgramSection::FExit { sleepable, name: _ } => {
let mut data =
ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level);
if *sleepable {
data.flags = BPF_F_SLEEPABLE;
}
Program::FExit(FExit { data })
}
ProgramSection::Extension { .. } => Program::Extension(Extension { ProgramSection::Extension { .. } => Program::Extension(Extension {
data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level),
}), }),

@ -5837,8 +5837,10 @@ pub aya_obj::obj::ProgramSection::Extension
pub aya_obj::obj::ProgramSection::Extension::name: alloc::string::String pub aya_obj::obj::ProgramSection::Extension::name: alloc::string::String
pub aya_obj::obj::ProgramSection::FEntry pub aya_obj::obj::ProgramSection::FEntry
pub aya_obj::obj::ProgramSection::FEntry::name: alloc::string::String pub aya_obj::obj::ProgramSection::FEntry::name: alloc::string::String
pub aya_obj::obj::ProgramSection::FEntry::sleepable: bool
pub aya_obj::obj::ProgramSection::FExit pub aya_obj::obj::ProgramSection::FExit
pub aya_obj::obj::ProgramSection::FExit::name: alloc::string::String pub aya_obj::obj::ProgramSection::FExit::name: alloc::string::String
pub aya_obj::obj::ProgramSection::FExit::sleepable: bool
pub aya_obj::obj::ProgramSection::KProbe pub aya_obj::obj::ProgramSection::KProbe
pub aya_obj::obj::ProgramSection::KProbe::name: alloc::string::String pub aya_obj::obj::ProgramSection::KProbe::name: alloc::string::String
pub aya_obj::obj::ProgramSection::KRetProbe pub aya_obj::obj::ProgramSection::KRetProbe
@ -5870,8 +5872,10 @@ pub aya_obj::obj::ProgramSection::TracePoint
pub aya_obj::obj::ProgramSection::TracePoint::name: alloc::string::String pub aya_obj::obj::ProgramSection::TracePoint::name: alloc::string::String
pub aya_obj::obj::ProgramSection::UProbe pub aya_obj::obj::ProgramSection::UProbe
pub aya_obj::obj::ProgramSection::UProbe::name: alloc::string::String pub aya_obj::obj::ProgramSection::UProbe::name: alloc::string::String
pub aya_obj::obj::ProgramSection::UProbe::sleepable: bool
pub aya_obj::obj::ProgramSection::URetProbe pub aya_obj::obj::ProgramSection::URetProbe
pub aya_obj::obj::ProgramSection::URetProbe::name: alloc::string::String pub aya_obj::obj::ProgramSection::URetProbe::name: alloc::string::String
pub aya_obj::obj::ProgramSection::URetProbe::sleepable: bool
pub aya_obj::obj::ProgramSection::Xdp pub aya_obj::obj::ProgramSection::Xdp
pub aya_obj::obj::ProgramSection::Xdp::frags: bool pub aya_obj::obj::ProgramSection::Xdp::frags: bool
pub aya_obj::obj::ProgramSection::Xdp::name: alloc::string::String pub aya_obj::obj::ProgramSection::Xdp::name: alloc::string::String
@ -6585,8 +6589,10 @@ pub aya_obj::ProgramSection::Extension
pub aya_obj::ProgramSection::Extension::name: alloc::string::String pub aya_obj::ProgramSection::Extension::name: alloc::string::String
pub aya_obj::ProgramSection::FEntry pub aya_obj::ProgramSection::FEntry
pub aya_obj::ProgramSection::FEntry::name: alloc::string::String pub aya_obj::ProgramSection::FEntry::name: alloc::string::String
pub aya_obj::ProgramSection::FEntry::sleepable: bool
pub aya_obj::ProgramSection::FExit pub aya_obj::ProgramSection::FExit
pub aya_obj::ProgramSection::FExit::name: alloc::string::String pub aya_obj::ProgramSection::FExit::name: alloc::string::String
pub aya_obj::ProgramSection::FExit::sleepable: bool
pub aya_obj::ProgramSection::KProbe pub aya_obj::ProgramSection::KProbe
pub aya_obj::ProgramSection::KProbe::name: alloc::string::String pub aya_obj::ProgramSection::KProbe::name: alloc::string::String
pub aya_obj::ProgramSection::KRetProbe pub aya_obj::ProgramSection::KRetProbe
@ -6618,8 +6624,10 @@ pub aya_obj::ProgramSection::TracePoint
pub aya_obj::ProgramSection::TracePoint::name: alloc::string::String pub aya_obj::ProgramSection::TracePoint::name: alloc::string::String
pub aya_obj::ProgramSection::UProbe pub aya_obj::ProgramSection::UProbe
pub aya_obj::ProgramSection::UProbe::name: alloc::string::String pub aya_obj::ProgramSection::UProbe::name: alloc::string::String
pub aya_obj::ProgramSection::UProbe::sleepable: bool
pub aya_obj::ProgramSection::URetProbe pub aya_obj::ProgramSection::URetProbe
pub aya_obj::ProgramSection::URetProbe::name: alloc::string::String pub aya_obj::ProgramSection::URetProbe::name: alloc::string::String
pub aya_obj::ProgramSection::URetProbe::sleepable: bool
pub aya_obj::ProgramSection::Xdp pub aya_obj::ProgramSection::Xdp
pub aya_obj::ProgramSection::Xdp::frags: bool pub aya_obj::ProgramSection::Xdp::frags: bool
pub aya_obj::ProgramSection::Xdp::name: alloc::string::String pub aya_obj::ProgramSection::Xdp::name: alloc::string::String

Loading…
Cancel
Save