aya-bpf-macros: Remove pop_required_string_args

I got a little carried away with refactoring the macros and started
making some macro arguments required when they previously were not.
While I'm all for doing this eventually, for stronger type guarantees
and de-duplicating information from BPF and userspace, it's premature
to do that now.

Signed-off-by: Dave Tucker <dave@dtucker.co.uk>
pull/713/head
Dave Tucker 2 years ago
parent ba0c7f8ac9
commit 157493579f

@ -70,30 +70,6 @@ pub(crate) fn pop_bool_arg(args: &mut Args, name: &str) -> bool {
value.is_some() value.is_some()
} }
pub(crate) fn pop_required_string_arg(args: &mut Args, name: &str) -> Result<String> {
let value = match args.args.iter().position(|arg| match arg {
Arg::String(name_val) => name_val.name == name,
Arg::Bool(_) => false,
}) {
Some(index) => Some(args.args.remove(index)),
None => None,
};
match value {
Some(Arg::String(value)) => Ok(value.value.value()),
Some(Arg::Bool(_)) => unreachable!("arg bool were filtered out"),
None => {
let tokens = match args.args.first().unwrap() {
Arg::String(name_val) => &name_val.name,
Arg::Bool(ident) => ident,
};
Err(Error::new_spanned(
tokens,
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) {
let tokens = match arg { let tokens = match arg {

@ -4,24 +4,33 @@ 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_required_string_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>,
} }
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_string_arg(&mut args, "function")?; let mut function = None;
if !attrs.is_empty() {
let mut args: Args = syn::parse2(attrs)?;
if let Some(f) = pop_string_arg(&mut args, "function") {
function = Some(f);
}
err_on_unknown_args(&args)?; err_on_unknown_args(&args)?;
}
Ok(BtfTracePoint { item, function }) Ok(BtfTracePoint { item, function })
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> Result<TokenStream> {
let section_name: Cow<'_, _> = format!("tp_btf/{}", self.function).into(); let section_name: Cow<'_, _> = if self.function.is_none() {
"tp_btf".into()
} else {
format!("tp_btf/{}", self.function.as_ref().unwrap()).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;
@ -45,6 +54,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!(

@ -1,28 +1,30 @@
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_bool_arg, pop_required_string_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_string_arg(&mut args, "function")?; let mut function = None;
let sleepable = pop_bool_arg(&mut args, "sleepable"); let mut sleepable = false;
if !attrs.is_empty() {
let mut args = syn::parse2(attrs)?;
if let Some(f) = pop_string_arg(&mut args, "function") {
function = Some(f);
};
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,
@ -32,7 +34,11 @@ impl FEntry {
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 self.function.is_none() {
section_prefix.into()
} else {
format!("{}/{}", section_prefix, self.function.as_ref().unwrap()).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;
@ -56,6 +62,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"
@ -87,7 +120,6 @@ mod tests {
fn test_fentry_sleepable() { fn test_fentry_sleepable() {
let prog = FEntry::parse( let prog = FEntry::parse(
parse_quote! { parse_quote! {
function = "sys_clone",
sleepable sleepable
}, },
parse_quote! { parse_quote! {
@ -100,7 +132,7 @@ mod tests {
let expanded = prog.expand().unwrap(); let expanded = prog.expand().unwrap();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "fentry.s/sys_clone"] #[link_section = "fentry.s"]
fn sys_clone(ctx: *mut ::core::ffi::c_void) -> i32 { fn sys_clone(ctx: *mut ::core::ffi::c_void) -> i32 {
let _ = sys_clone(::aya_bpf::programs::FEntryContext::new(ctx)); let _ = sys_clone(::aya_bpf::programs::FEntryContext::new(ctx));
return 0; return 0;

@ -1,28 +1,30 @@
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_bool_arg, pop_required_string_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_string_arg(&mut args, "function")?; let mut function = None;
let sleepable = pop_bool_arg(&mut args, "sleepable"); let mut sleepable = false;
if !attrs.is_empty() {
let mut args = syn::parse2(attrs)?;
if let Some(f) = pop_string_arg(&mut args, "function") {
function = Some(f);
};
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,
@ -32,7 +34,11 @@ impl FExit {
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 self.function.is_none() {
section_prefix.into()
} else {
format!("{}/{}", section_prefix, self.function.as_ref().unwrap()).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;
@ -56,6 +62,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"

@ -1,28 +1,30 @@
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_bool_arg, pop_required_string_arg}; 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 = pop_required_string_arg(&mut args, "hook")?; let mut hook = None;
let sleepable = pop_bool_arg(&mut args, "sleepable"); let mut sleepable = false;
if !attrs.is_empty() {
let mut args = syn::parse2(attrs)?;
if let Some(h) = pop_string_arg(&mut args, "hook") {
hook = Some(h);
};
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,
@ -32,7 +34,11 @@ impl Lsm {
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 self.hook.is_none() {
section_prefix.into()
} else {
format!("{}/{}", section_prefix, self.hook.as_ref().unwrap()).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;

@ -1,31 +1,37 @@
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_string_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_string_arg(&mut args, "tracepoint")?; let mut tracepoint = None;
if !attrs.is_empty() {
let mut args = syn::parse2(attrs)?;
if let Some(tp) = pop_string_arg(&mut args, "tracepoint") {
tracepoint = Some(tp)
};
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 self.tracepoint.is_none() {
"raw_tp".into()
} else {
format!("raw_tp/{}", self.tracepoint.as_ref().unwrap()).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;

Loading…
Cancel
Save