Replace proc-macro-error with proc-macro2-diagnostics

proc-macro-error is unmaintained.
reviewable/pr1109/r1
Tamir Duberstein 2 months ago committed by Michal Rostecki
parent dae394e199
commit 5a43bedc01

@ -81,8 +81,8 @@ nix = { version = "0.29.0", default-features = false }
num_enum = { version = "0.7", default-features = false } num_enum = { version = "0.7", default-features = false }
object = { version = "0.36", default-features = false } object = { version = "0.36", default-features = false }
once_cell = { version = "1.20.1", default-features = false } once_cell = { version = "1.20.1", default-features = false }
proc-macro-error = { version = "1.0", default-features = false }
proc-macro2 = { version = "1", default-features = false } proc-macro2 = { version = "1", default-features = false }
proc-macro2-diagnostics = { version = "0.10.1", default-features = false }
public-api = { version = "0.42.0", default-features = false } public-api = { version = "0.42.0", default-features = false }
quote = { version = "1", default-features = false } quote = { version = "1", default-features = false }
rand = { version = "0.8", default-features = false } rand = { version = "0.8", default-features = false }

@ -13,7 +13,7 @@ proc-macro = true
[dependencies] [dependencies]
proc-macro2 = { workspace = true } proc-macro2 = { workspace = true }
proc-macro-error = { workspace = true } proc-macro2-diagnostics = { workspace = true }
quote = { workspace = true } quote = { workspace = true }
syn = { workspace = true, default-features = true, features = ["full"] } syn = { workspace = true, default-features = true, features = ["full"] }

@ -18,28 +18,33 @@ impl BtfTracePoint {
let function = pop_string_arg(&mut args, "function"); let function = pop_string_arg(&mut args, "function");
err_on_unknown_args(&args)?; err_on_unknown_args(&args)?;
Ok(BtfTracePoint { item, function }) Ok(Self { item, function })
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> TokenStream {
let section_name: Cow<'_, _> = if let Some(function) = &self.function { let Self { item, function } = self;
let ItemFn {
attrs: _,
vis,
sig,
block: _,
} = item;
let section_name: Cow<'_, _> = if let Some(function) = function {
format!("tp_btf/{}", function).into() format!("tp_btf/{}", function).into()
} else { } else {
"tp_btf".into() "tp_btf".into()
}; };
let fn_vis = &self.item.vis; let fn_name = &sig.ident;
let fn_name = self.item.sig.ident.clone(); quote! {
let item = &self.item;
Ok(quote! {
#[no_mangle] #[no_mangle]
#[link_section = #section_name] #[link_section = #section_name]
#fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> i32 { #vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> i32 {
let _ = #fn_name(::aya_ebpf::programs::BtfTracePointContext::new(ctx)); let _ = #fn_name(::aya_ebpf::programs::BtfTracePointContext::new(ctx));
return 0; return 0;
#item #item
} }
}) }
} }
} }
@ -60,7 +65,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote!( let expected = quote!(
#[no_mangle] #[no_mangle]
#[link_section = "tp_btf"] #[link_section = "tp_btf"]
@ -87,7 +92,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote!( let expected = quote!(
#[no_mangle] #[no_mangle]
#[link_section = "tp_btf/some_func"] #[link_section = "tp_btf/some_func"]

@ -1,34 +1,39 @@
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use proc_macro_error::abort; use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _};
use quote::quote; use quote::quote;
use syn::{ItemFn, Result}; use syn::{spanned::Spanned as _, ItemFn};
pub(crate) struct CgroupDevice { pub(crate) struct CgroupDevice {
item: ItemFn, item: ItemFn,
} }
impl CgroupDevice { impl CgroupDevice {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self, Diagnostic> {
if !attrs.is_empty() { if !attrs.is_empty() {
abort!(attrs, "unexpected attribute") return Err(attrs.span().error("unexpected attribute"));
} }
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
Ok(CgroupDevice { item }) Ok(Self { item })
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> TokenStream {
let fn_vis = &self.item.vis; let Self { item } = self;
let fn_name = self.item.sig.ident.clone(); let ItemFn {
let item = &self.item; attrs: _,
Ok(quote! { vis,
sig,
block: _,
} = item;
let fn_name = &sig.ident;
quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup/dev"] #[link_section = "cgroup/dev"]
#fn_vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::bpf_cgroup_dev_ctx) -> i32 { #vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::bpf_cgroup_dev_ctx) -> i32 {
return #fn_name(::aya_ebpf::programs::DeviceContext::new(ctx)); return #fn_name(::aya_ebpf::programs::DeviceContext::new(ctx));
#item #item
} }
}) }
} }
} }
@ -49,7 +54,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup/dev"] #[link_section = "cgroup/dev"]

@ -1,48 +1,52 @@
use std::borrow::Cow; use std::borrow::Cow;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use proc_macro_error::abort; use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _};
use quote::quote; use quote::quote;
use syn::{Ident, ItemFn, Result}; use syn::{Ident, ItemFn};
pub(crate) struct CgroupSkb { pub(crate) struct CgroupSkb {
item: ItemFn, item: ItemFn,
attach_type: Option<String>, attach_type: Option<Ident>,
} }
impl CgroupSkb { impl CgroupSkb {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<CgroupSkb> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self, Diagnostic> {
let item: ItemFn = syn::parse2(item)?; let item: ItemFn = syn::parse2(item)?;
let mut attach_type = None; let attach_type = if attrs.is_empty() {
if !attrs.is_empty() { None
} else {
let ident: Ident = syn::parse2(attrs)?; let ident: Ident = syn::parse2(attrs)?;
match ident.to_string().as_str() { if ident != "ingress" && ident != "egress" {
"ingress" | "egress" => (), return Err(ident.span().error("invalid attach type"));
_ => abort!(ident, "invalid attach type"),
} }
attach_type = Some(ident.to_string()); Some(ident)
} };
Ok(CgroupSkb { item, attach_type }) Ok(Self { item, attach_type })
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> TokenStream {
let section_name: Cow<'_, _> = if self.attach_type.is_some() { let Self { item, attach_type } = self;
format!("cgroup_skb/{}", self.attach_type.as_ref().unwrap()).into() let ItemFn {
} else { attrs: _,
"cgroup/skb".into() vis,
sig,
block: _,
} = item;
let section_name: Cow<'_, _> = match attach_type {
Some(attach_type) => format!("cgroup_skb/{attach_type}").into(),
None => "cgroup/skb".into(),
}; };
let fn_vis = &self.item.vis; let fn_name = &sig.ident;
let fn_name = self.item.sig.ident.clone(); quote! {
let item = &self.item;
Ok(quote! {
#[no_mangle] #[no_mangle]
#[link_section = #section_name] #[link_section = #section_name]
#fn_vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::__sk_buff) -> i32 { #vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::__sk_buff) -> i32 {
return #fn_name(::aya_ebpf::programs::SkBuffContext::new(ctx)); return #fn_name(::aya_ebpf::programs::SkBuffContext::new(ctx));
#item #item
} }
}) }
} }
} }
@ -63,7 +67,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup/skb"] #[link_section = "cgroup/skb"]
@ -89,7 +93,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup_skb/egress"] #[link_section = "cgroup_skb/egress"]
@ -115,7 +119,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup_skb/ingress"] #[link_section = "cgroup_skb/ingress"]
@ -141,7 +145,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup_skb/egress"] #[link_section = "cgroup_skb/egress"]
@ -167,7 +171,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup_skb/egress"] #[link_section = "cgroup_skb/egress"]
@ -193,7 +197,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup_skb/egress"] #[link_section = "cgroup_skb/egress"]

@ -1,46 +1,51 @@
use std::borrow::Cow; use std::borrow::Cow;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use proc_macro_error::abort; use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _};
use quote::quote; use quote::quote;
use syn::{Ident, ItemFn, Result}; use syn::{spanned::Spanned as _, Ident, ItemFn};
pub(crate) struct CgroupSock { pub(crate) struct CgroupSock {
item: ItemFn, item: ItemFn,
attach_type: String, attach_type: Ident,
} }
impl CgroupSock { impl CgroupSock {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<CgroupSock> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self, Diagnostic> {
if attrs.is_empty() { if attrs.is_empty() {
abort!(attrs, "missing attach type") return Err(attrs.span().error("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() { if attach_type != "post_bind4"
"post_bind4" | "post_bind6" | "sock_create" | "sock_release" => (), && attach_type != "post_bind6"
_ => abort!(attach_type, "invalid attach type"), && attach_type != "sock_create"
&& attach_type != "sock_release"
{
return Err(attach_type.span().error("invalid attach type"));
} }
Ok(CgroupSock { Ok(Self { item, attach_type })
item,
attach_type: attach_type.to_string(),
})
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> TokenStream {
let section_name: Cow<'_, _> = format!("cgroup/{}", self.attach_type).into(); let Self { item, attach_type } = self;
let fn_vis = &self.item.vis; let ItemFn {
let fn_name = self.item.sig.ident.clone(); attrs: _,
let item = &self.item; vis,
Ok(quote! { sig,
block: _,
} = item;
let section_name: Cow<'_, _> = format!("cgroup/{attach_type}").into();
let fn_name = &sig.ident;
quote! {
#[no_mangle] #[no_mangle]
#[link_section = #section_name] #[link_section = #section_name]
#fn_vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::bpf_sock) -> i32 { #vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::bpf_sock) -> i32 {
return #fn_name(::aya_ebpf::programs::SockContext::new(ctx)); return #fn_name(::aya_ebpf::programs::SockContext::new(ctx));
#item #item
} }
}) }
} }
} }
@ -61,7 +66,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup/post_bind4"] #[link_section = "cgroup/post_bind4"]
@ -87,7 +92,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup/post_bind6"] #[link_section = "cgroup/post_bind6"]
@ -112,7 +117,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup/sock_create"] #[link_section = "cgroup/sock_create"]
@ -137,7 +142,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup/sock_release"] #[link_section = "cgroup/sock_release"]

@ -1,48 +1,59 @@
use std::borrow::Cow; use std::borrow::Cow;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use proc_macro_error::abort; use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _};
use quote::quote; use quote::quote;
use syn::{Ident, ItemFn, Result}; use syn::{spanned::Spanned as _, Ident, ItemFn};
pub(crate) struct CgroupSockAddr { pub(crate) struct CgroupSockAddr {
item: ItemFn, item: ItemFn,
attach_type: String, attach_type: Ident,
} }
impl CgroupSockAddr { impl CgroupSockAddr {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self, Diagnostic> {
if attrs.is_empty() { if attrs.is_empty() {
abort!(attrs, "missing attach type") return Err(attrs.span().error("missing attach type"));
} }
let item = syn::parse2(item)?; 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() { if attach_type != "connect4"
"connect4" | "connect6" | "bind4" | "bind6" | "getpeername4" | "getpeername6" && attach_type != "connect6"
| "getsockname4" | "getsockname6" | "sendmsg4" | "sendmsg6" | "recvmsg4" && attach_type != "bind4"
| "recvmsg6" => (), && attach_type != "bind6"
_ => abort!(attach_type, "invalid attach type"), && attach_type != "getpeername4"
&& attach_type != "getpeername6"
&& attach_type != "getsockname4"
&& attach_type != "getsockname6"
&& attach_type != "sendmsg4"
&& attach_type != "sendmsg6"
&& attach_type != "recvmsg4"
&& attach_type != "recvmsg6"
{
return Err(attach_type.span().error("invalid attach type"));
} }
Ok(CgroupSockAddr { Ok(Self { item, attach_type })
item,
attach_type: attach_type.to_string(),
})
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> TokenStream {
let section_name: Cow<'_, _> = format!("cgroup/{}", self.attach_type).into(); let Self { item, attach_type } = self;
let fn_vis = &self.item.vis; let ItemFn {
let fn_name = self.item.sig.ident.clone(); attrs: _,
let item = &self.item; vis,
Ok(quote! { sig,
block: _,
} = item;
let section_name: Cow<'_, _> = format!("cgroup/{attach_type}").into();
let fn_name = &sig.ident;
quote! {
#[no_mangle] #[no_mangle]
#[link_section = #section_name] #[link_section = #section_name]
#fn_vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::bpf_sock_addr) -> i32 { #vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::bpf_sock_addr) -> i32 {
return #fn_name(::aya_ebpf::programs::SockAddrContext::new(ctx)); return #fn_name(::aya_ebpf::programs::SockAddrContext::new(ctx));
#item #item
} }
}) }
} }
} }
@ -63,7 +74,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup/connect4"] #[link_section = "cgroup/connect4"]
@ -89,7 +100,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup/connect6"] #[link_section = "cgroup/connect6"]
@ -115,7 +126,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup/bind4"] #[link_section = "cgroup/bind4"]
@ -141,7 +152,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup/bind6"] #[link_section = "cgroup/bind6"]
@ -167,7 +178,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup/getpeername4"] #[link_section = "cgroup/getpeername4"]
@ -193,7 +204,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup/getpeername6"] #[link_section = "cgroup/getpeername6"]
@ -219,7 +230,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup/getsockname4"] #[link_section = "cgroup/getsockname4"]
@ -245,7 +256,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup/getsockname6"] #[link_section = "cgroup/getsockname6"]
@ -271,7 +282,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup/sendmsg4"] #[link_section = "cgroup/sendmsg4"]
@ -297,7 +308,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup/sendmsg6"] #[link_section = "cgroup/sendmsg6"]
@ -323,7 +334,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup/recvmsg4"] #[link_section = "cgroup/recvmsg4"]
@ -349,7 +360,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup/recvmsg6"] #[link_section = "cgroup/recvmsg6"]

@ -1,46 +1,50 @@
use std::borrow::Cow; use std::borrow::Cow;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use proc_macro_error::abort; use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _};
use quote::quote; use quote::quote;
use syn::{Ident, ItemFn, Result}; use syn::{spanned::Spanned as _, Ident, ItemFn};
pub(crate) struct CgroupSockopt { pub(crate) struct CgroupSockopt {
item: ItemFn, item: ItemFn,
attach_type: String, attach_type: Ident,
} }
impl CgroupSockopt { impl CgroupSockopt {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<CgroupSockopt> { pub(crate) fn parse(
attrs: TokenStream,
item: TokenStream,
) -> Result<CgroupSockopt, Diagnostic> {
if attrs.is_empty() { if attrs.is_empty() {
abort!(attrs, "expected attach type"); return Err(attrs.span().error("missing attach type"));
} }
let item = syn::parse2(item)?; 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() { if attach_type != "getsockopt" && attach_type != "setsockopt" {
"getsockopt" | "setsockopt" => (), return Err(attach_type.span().error("invalid attach type"));
_ => abort!(attach_type, "invalid attach type"),
} }
Ok(CgroupSockopt { Ok(Self { item, attach_type })
item,
attach_type: attach_type.to_string(),
})
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> TokenStream {
let section_name: Cow<'_, _> = format!("cgroup/{}", self.attach_type).into(); let Self { item, attach_type } = self;
let fn_vis = &self.item.vis; let ItemFn {
let fn_name = self.item.sig.ident.clone(); attrs: _,
let item = &self.item; vis,
Ok(quote! { sig,
block: _,
} = item;
let section_name: Cow<'_, _> = format!("cgroup/{attach_type}").into();
let fn_name = &sig.ident;
quote! {
#[no_mangle] #[no_mangle]
#[link_section = #section_name] #[link_section = #section_name]
#fn_vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::bpf_sockopt) -> i32 { #vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::bpf_sockopt) -> i32 {
return #fn_name(::aya_ebpf::programs::SockoptContext::new(ctx)); return #fn_name(::aya_ebpf::programs::SockoptContext::new(ctx));
#item #item
} }
}) }
} }
} }
@ -61,7 +65,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote!( let expected = quote!(
#[no_mangle] #[no_mangle]
#[link_section = "cgroup/getsockopt"] #[link_section = "cgroup/getsockopt"]
@ -87,7 +91,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote!( let expected = quote!(
#[no_mangle] #[no_mangle]
#[link_section = "cgroup/setsockopt"] #[link_section = "cgroup/setsockopt"]

@ -1,34 +1,39 @@
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use proc_macro_error::abort; use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _};
use quote::quote; use quote::quote;
use syn::{ItemFn, Result}; use syn::{spanned::Spanned as _, ItemFn};
pub(crate) struct CgroupSysctl { pub(crate) struct CgroupSysctl {
item: ItemFn, item: ItemFn,
} }
impl CgroupSysctl { impl CgroupSysctl {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self, Diagnostic> {
if !attrs.is_empty() { if !attrs.is_empty() {
abort!(attrs, "unexpected attribute") return Err(attrs.span().error("unexpected attribute"));
} }
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
Ok(CgroupSysctl { item }) Ok(Self { item })
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> TokenStream {
let fn_vis = &self.item.vis; let Self { item } = self;
let fn_name = self.item.sig.ident.clone(); let ItemFn {
let item = &self.item; attrs: _,
Ok(quote! { vis,
sig,
block: _,
} = item;
let fn_name = &sig.ident;
quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup/sysctl"] #[link_section = "cgroup/sysctl"]
#fn_vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::bpf_sysctl) -> i32 { #vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::bpf_sysctl) -> i32 {
return #fn_name(::aya_ebpf::programs::SysctlContext::new(ctx)); return #fn_name(::aya_ebpf::programs::SysctlContext::new(ctx));
#item #item
} }
}) }
} }
} }
@ -49,7 +54,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "cgroup/sysctl"] #[link_section = "cgroup/sysctl"]

@ -13,39 +13,48 @@ pub(crate) struct FEntry {
} }
impl FEntry { impl FEntry {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<FEntry> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self> {
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
let mut args = syn::parse2(attrs)?; let mut args = syn::parse2(attrs)?;
let function = pop_string_arg(&mut args, "function"); let function = pop_string_arg(&mut args, "function");
let sleepable = pop_bool_arg(&mut args, "sleepable"); let sleepable = pop_bool_arg(&mut args, "sleepable");
err_on_unknown_args(&args)?; err_on_unknown_args(&args)?;
Ok(FEntry { Ok(Self {
item, item,
function, function,
sleepable, sleepable,
}) })
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> TokenStream {
let section_prefix = if self.sleepable { "fentry.s" } else { "fentry" }; let Self {
let section_name: Cow<'_, _> = if let Some(function) = &self.function { item,
function,
sleepable,
} = self;
let ItemFn {
attrs: _,
vis,
sig,
block: _,
} = item;
let section_prefix = if *sleepable { "fentry.s" } else { "fentry" };
let section_name: Cow<'_, _> = if let Some(function) = function {
format!("{}/{}", section_prefix, function).into() format!("{}/{}", section_prefix, function).into()
} else { } else {
section_prefix.into() section_prefix.into()
}; };
let fn_vis = &self.item.vis; let fn_name = &sig.ident;
let fn_name = self.item.sig.ident.clone(); quote! {
let item = &self.item;
Ok(quote! {
#[no_mangle] #[no_mangle]
#[link_section = #section_name] #[link_section = #section_name]
#fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> i32 { #vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> i32 {
let _ = #fn_name(::aya_ebpf::programs::FEntryContext::new(ctx)); let _ = #fn_name(::aya_ebpf::programs::FEntryContext::new(ctx));
return 0; return 0;
#item #item
} }
}) }
} }
} }
@ -66,7 +75,7 @@ mod tests {
}, },
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "fentry"] #[link_section = "fentry"]
@ -95,7 +104,7 @@ mod tests {
}, },
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "fentry/sys_clone"] #[link_section = "fentry/sys_clone"]
@ -124,7 +133,7 @@ mod tests {
}, },
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "fentry.s"] #[link_section = "fentry.s"]

@ -13,39 +13,48 @@ pub(crate) struct FExit {
} }
impl FExit { impl FExit {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<FExit> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self> {
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
let mut args = syn::parse2(attrs)?; let mut args = syn::parse2(attrs)?;
let function = pop_string_arg(&mut args, "function"); let function = pop_string_arg(&mut args, "function");
let sleepable = pop_bool_arg(&mut args, "sleepable"); let sleepable = pop_bool_arg(&mut args, "sleepable");
err_on_unknown_args(&args)?; err_on_unknown_args(&args)?;
Ok(FExit { Ok(Self {
item, item,
function, function,
sleepable, sleepable,
}) })
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> TokenStream {
let section_prefix = if self.sleepable { "fexit.s" } else { "fexit" }; let Self {
let section_name: Cow<'_, _> = if let Some(function) = &self.function { item,
function,
sleepable,
} = self;
let ItemFn {
attrs: _,
vis,
sig,
block: _,
} = item;
let section_prefix = if *sleepable { "fexit.s" } else { "fexit" };
let section_name: Cow<'_, _> = if let Some(function) = function {
format!("{}/{}", section_prefix, function).into() format!("{}/{}", section_prefix, function).into()
} else { } else {
section_prefix.into() section_prefix.into()
}; };
let fn_vis = &self.item.vis; let fn_name = &sig.ident;
let fn_name = self.item.sig.ident.clone(); quote! {
let item = &self.item;
Ok(quote! {
#[no_mangle] #[no_mangle]
#[link_section = #section_name] #[link_section = #section_name]
#fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> i32 { #vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> i32 {
let _ = #fn_name(::aya_ebpf::programs::FExitContext::new(ctx)); let _ = #fn_name(::aya_ebpf::programs::FExitContext::new(ctx));
return 0; return 0;
#item #item
} }
}) }
} }
} }
@ -66,7 +75,7 @@ mod tests {
}, },
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "fexit"] #[link_section = "fexit"]
@ -95,7 +104,7 @@ mod tests {
}, },
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "fexit/sys_clone"] #[link_section = "fexit/sys_clone"]
@ -124,7 +133,7 @@ mod tests {
}, },
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "fexit.s/sys_clone"] #[link_section = "fexit.s/sys_clone"]

@ -1,8 +1,9 @@
use std::borrow::Cow; use std::borrow::Cow;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _};
use quote::quote; use quote::quote;
use syn::{ItemFn, Result}; use syn::{spanned::Spanned as _, ItemFn};
use crate::args::{err_on_unknown_args, pop_string_arg}; use crate::args::{err_on_unknown_args, pop_string_arg};
@ -31,14 +32,23 @@ 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<Self, Diagnostic> {
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
let span = attrs.span();
let mut args = syn::parse2(attrs)?; let mut args = syn::parse2(attrs)?;
let function = pop_string_arg(&mut args, "function"); let function = pop_string_arg(&mut args, "function");
let offset = pop_string_arg(&mut args, "offset").map(|v| v.parse::<u64>().unwrap()); let offset = pop_string_arg(&mut args, "offset")
.as_deref()
.map(str::parse)
.transpose()
.map_err(|err| span.error(format!("failed to parse `offset` argument: {}", err)))?;
err_on_unknown_args(&args)?; err_on_unknown_args(&args)?;
Ok(KProbe { Ok(Self {
kind, kind,
item, item,
function, function,
@ -46,39 +56,42 @@ impl KProbe {
}) })
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> TokenStream {
let section_name: Cow<'_, _> = if self.function.is_some() && self.offset.is_some() { let Self {
format!( kind,
"{}/{}+{}", function,
self.kind, offset,
self.function.as_ref().unwrap(), item,
self.offset.unwrap() } = self;
) let ItemFn {
.into() attrs: _,
} else if self.function.is_some() { vis,
format!("{}/{}", self.kind, self.function.as_ref().unwrap()).into() sig,
} else { block: _,
format!("{}", self.kind).into() } = item;
let section_name: Cow<'_, _> = match function {
None => self.kind.to_string().into(),
Some(function) => match offset {
None => format!("{kind}/{function}").into(),
Some(offset) => format!("{kind}/{function}+{offset}").into(),
},
}; };
let probe_type = if section_name.as_ref().starts_with("kprobe") { let probe_type = if section_name.as_ref().starts_with("kprobe") {
quote! { ProbeContext } quote! { ProbeContext }
} else { } else {
quote! { RetProbeContext } quote! { RetProbeContext }
}; };
let fn_vis = &self.item.vis; let fn_name = &sig.ident;
let fn_name = self.item.sig.ident.clone(); quote! {
let item = &self.item;
Ok(quote! {
#[no_mangle] #[no_mangle]
#[link_section = #section_name] #[link_section = #section_name]
#fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> u32 { #vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> u32 {
let _ = #fn_name(::aya_ebpf::programs::#probe_type::new(ctx)); let _ = #fn_name(::aya_ebpf::programs::#probe_type::new(ctx));
return 0; return 0;
#item #item
} }
}) }
} }
} }
@ -101,7 +114,7 @@ mod tests {
) )
.unwrap(); .unwrap();
assert_eq!( assert_eq!(
kprobe.expand().unwrap().to_string(), kprobe.expand().to_string(),
quote! { quote! {
#[no_mangle] #[no_mangle]
#[link_section = "kprobe"] #[link_section = "kprobe"]
@ -133,7 +146,7 @@ mod tests {
) )
.unwrap(); .unwrap();
assert_eq!( assert_eq!(
kprobe.expand().unwrap().to_string(), kprobe.expand().to_string(),
quote! { quote! {
#[no_mangle] #[no_mangle]
#[link_section = "kprobe/fib_lookup"] #[link_section = "kprobe/fib_lookup"]
@ -166,7 +179,7 @@ mod tests {
) )
.unwrap(); .unwrap();
assert_eq!( assert_eq!(
kprobe.expand().unwrap().to_string(), kprobe.expand().to_string(),
quote! { quote! {
#[no_mangle] #[no_mangle]
#[link_section = "kprobe/fib_lookup+10"] #[link_section = "kprobe/fib_lookup+10"]
@ -196,7 +209,7 @@ mod tests {
) )
.unwrap(); .unwrap();
assert_eq!( assert_eq!(
kprobe.expand().unwrap().to_string(), kprobe.expand().to_string(),
quote! { quote! {
#[no_mangle] #[no_mangle]
#[link_section = "kretprobe"] #[link_section = "kretprobe"]

@ -37,7 +37,6 @@ use lsm::Lsm;
use map::Map; use map::Map;
use perf_event::PerfEvent; use perf_event::PerfEvent;
use proc_macro::TokenStream; use proc_macro::TokenStream;
use proc_macro_error::{abort, proc_macro_error};
use raw_tracepoint::RawTracePoint; use raw_tracepoint::RawTracePoint;
use sk_lookup::SkLookup; use sk_lookup::SkLookup;
use sk_msg::SkMsg; use sk_msg::SkMsg;
@ -48,83 +47,69 @@ use tc::SchedClassifier;
use tracepoint::TracePoint; use tracepoint::TracePoint;
use uprobe::{UProbe, UProbeKind}; use uprobe::{UProbe, UProbeKind};
use xdp::Xdp; use xdp::Xdp;
#[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn map(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn map(attrs: TokenStream, item: TokenStream) -> TokenStream {
match Map::parse(attrs.into(), item.into()) { match Map::parse(attrs.into(), item.into()) {
Ok(prog) => prog Ok(prog) => prog.expand(),
.expand() Err(err) => err.into_compile_error(),
.unwrap_or_else(|err| abort!(err.span(), "{}", err))
.into(),
Err(err) => abort!(err.span(), "{}", err),
} }
.into()
} }
#[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn kprobe(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn kprobe(attrs: TokenStream, item: TokenStream) -> TokenStream {
match KProbe::parse(KProbeKind::KProbe, attrs.into(), item.into()) { match KProbe::parse(KProbeKind::KProbe, attrs.into(), item.into()) {
Ok(prog) => prog Ok(prog) => prog.expand(),
.expand() Err(err) => err.emit_as_expr_tokens(),
.unwrap_or_else(|err| abort!(err.span(), "{}", err))
.into(),
Err(err) => abort!(err.span(), "{}", err),
} }
.into()
} }
#[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn kretprobe(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn kretprobe(attrs: TokenStream, item: TokenStream) -> TokenStream {
match KProbe::parse(KProbeKind::KRetProbe, attrs.into(), item.into()) { match KProbe::parse(KProbeKind::KRetProbe, attrs.into(), item.into()) {
Ok(prog) => prog Ok(prog) => prog.expand(),
.expand() Err(err) => err.emit_as_expr_tokens(),
.unwrap_or_else(|err| abort!(err.span(), "{}", err))
.into(),
Err(err) => abort!(err.span(), "{}", err),
} }
.into()
} }
#[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn uprobe(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn uprobe(attrs: TokenStream, item: TokenStream) -> TokenStream {
match UProbe::parse(UProbeKind::UProbe, attrs.into(), item.into()) { match UProbe::parse(UProbeKind::UProbe, attrs.into(), item.into()) {
Ok(prog) => prog Ok(prog) => match prog.expand() {
.expand() Ok(tokens) => tokens,
.unwrap_or_else(|err| abort!(err.span(), "{}", err)) Err(err) => err.emit_as_expr_tokens(),
.into(), },
Err(err) => abort!(err.span(), "{}", err), Err(err) => err.emit_as_expr_tokens(),
} }
.into()
} }
#[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn uretprobe(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn uretprobe(attrs: TokenStream, item: TokenStream) -> TokenStream {
match UProbe::parse(UProbeKind::URetProbe, attrs.into(), item.into()) { match UProbe::parse(UProbeKind::URetProbe, attrs.into(), item.into()) {
Ok(prog) => prog Ok(prog) => match prog.expand() {
.expand() Ok(tokens) => tokens,
.unwrap_or_else(|err| abort!(err.span(), "{}", err)) Err(err) => err.emit_as_expr_tokens(),
.into(), },
Err(err) => abort!(err.span(), "{}", err), Err(err) => err.emit_as_expr_tokens(),
} }
.into()
} }
#[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn sock_ops(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn sock_ops(attrs: TokenStream, item: TokenStream) -> TokenStream {
match SockOps::parse(attrs.into(), item.into()) { match SockOps::parse(attrs.into(), item.into()) {
Ok(prog) => prog Ok(prog) => prog.expand(),
.expand() Err(err) => err.emit_as_expr_tokens(),
.unwrap_or_else(|err| abort!(err.span(), "{}", err))
.into(),
Err(err) => abort!(err.span(), "{}", err),
} }
.into()
} }
#[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn sk_msg(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn sk_msg(attrs: TokenStream, item: TokenStream) -> TokenStream {
match SkMsg::parse(attrs.into(), item.into()) { match SkMsg::parse(attrs.into(), item.into()) {
Ok(prog) => prog Ok(prog) => prog.expand(),
.expand() Err(err) => err.emit_as_expr_tokens(),
.unwrap_or_else(|err| abort!(err.span(), "{}", err))
.into(),
Err(err) => abort!(err.span(), "{}", err),
} }
.into()
} }
/// Marks a function as an eBPF XDP program that can be attached to a network interface. /// Marks a function as an eBPF XDP program that can be attached to a network interface.
@ -149,60 +134,46 @@ pub fn sk_msg(attrs: TokenStream, item: TokenStream) -> TokenStream {
/// XDP_PASS /// XDP_PASS
/// } /// }
/// ``` /// ```
#[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn xdp(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn xdp(attrs: TokenStream, item: TokenStream) -> TokenStream {
match Xdp::parse(attrs.into(), item.into()) { match Xdp::parse(attrs.into(), item.into()) {
Ok(prog) => prog Ok(prog) => prog.expand(),
.expand() Err(err) => err.emit_as_expr_tokens(),
.unwrap_or_else(|err| abort!(err.span(), "{}", err))
.into(),
Err(err) => abort!(err.span(), "{}", err),
} }
.into()
} }
#[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn classifier(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn classifier(attrs: TokenStream, item: TokenStream) -> TokenStream {
match SchedClassifier::parse(attrs.into(), item.into()) { match SchedClassifier::parse(attrs.into(), item.into()) {
Ok(prog) => prog Ok(prog) => prog.expand(),
.expand() Err(err) => err.emit_as_expr_tokens(),
.unwrap_or_else(|err| abort!(err.span(), "{}", err))
.into(),
Err(err) => abort!(err.span(), "{}", err),
} }
.into()
} }
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn cgroup_sysctl(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn cgroup_sysctl(attrs: TokenStream, item: TokenStream) -> TokenStream {
match CgroupSysctl::parse(attrs.into(), item.into()) { match CgroupSysctl::parse(attrs.into(), item.into()) {
Ok(prog) => prog Ok(prog) => prog.expand(),
.expand() Err(err) => err.emit_as_expr_tokens(),
.unwrap_or_else(|err| abort!(err.span(), "{}", err))
.into(),
Err(err) => abort!(err.span(), "{}", err),
} }
.into()
} }
#[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn cgroup_sockopt(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn cgroup_sockopt(attrs: TokenStream, item: TokenStream) -> TokenStream {
match CgroupSockopt::parse(attrs.into(), item.into()) { match CgroupSockopt::parse(attrs.into(), item.into()) {
Ok(prog) => prog Ok(prog) => prog.expand(),
.expand() Err(err) => err.emit_as_expr_tokens(),
.unwrap_or_else(|err| abort!(err.span(), "{}", err))
.into(),
Err(err) => abort!(err.span(), "{}", err),
} }
.into()
} }
#[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn cgroup_skb(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn cgroup_skb(attrs: TokenStream, item: TokenStream) -> TokenStream {
match CgroupSkb::parse(attrs.into(), item.into()) { match CgroupSkb::parse(attrs.into(), item.into()) {
Ok(prog) => prog Ok(prog) => prog.expand(),
.expand() Err(err) => err.emit_as_expr_tokens(),
.unwrap_or_else(|err| abort!(err.span(), "{}", err))
.into(),
Err(err) => abort!(err.span(), "{}", err),
} }
.into()
} }
/// Marks a function as a [`CgroupSockAddr`] eBPF program. /// Marks a function as a [`CgroupSockAddr`] eBPF program.
@ -239,51 +210,39 @@ pub fn cgroup_skb(attrs: TokenStream, item: TokenStream) -> TokenStream {
/// Ok(0) /// Ok(0)
/// } /// }
/// ``` /// ```
#[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn cgroup_sock_addr(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn cgroup_sock_addr(attrs: TokenStream, item: TokenStream) -> TokenStream {
match CgroupSockAddr::parse(attrs.into(), item.into()) { match CgroupSockAddr::parse(attrs.into(), item.into()) {
Ok(prog) => prog Ok(prog) => prog.expand(),
.expand() Err(err) => err.emit_as_expr_tokens(),
.unwrap_or_else(|err| abort!(err.span(), "{}", err))
.into(),
Err(err) => abort!(err.span(), "{}", err),
} }
.into()
} }
#[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn cgroup_sock(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn cgroup_sock(attrs: TokenStream, item: TokenStream) -> TokenStream {
match CgroupSock::parse(attrs.into(), item.into()) { match CgroupSock::parse(attrs.into(), item.into()) {
Ok(prog) => prog Ok(prog) => prog.expand(),
.expand() Err(err) => err.emit_as_expr_tokens(),
.unwrap_or_else(|err| abort!(err.span(), "{}", err))
.into(),
Err(err) => abort!(err.span(), "{}", err),
} }
.into()
} }
#[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn tracepoint(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn tracepoint(attrs: TokenStream, item: TokenStream) -> TokenStream {
match TracePoint::parse(attrs.into(), item.into()) { match TracePoint::parse(attrs.into(), item.into()) {
Ok(prog) => prog Ok(prog) => prog.expand(),
.expand() Err(err) => err.emit_as_expr_tokens(),
.unwrap_or_else(|err| abort!(err.span(), "{}", err))
.into(),
Err(err) => abort!(err.span(), "{}", err),
} }
.into()
} }
#[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn perf_event(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn perf_event(attrs: TokenStream, item: TokenStream) -> TokenStream {
match PerfEvent::parse(attrs.into(), item.into()) { match PerfEvent::parse(attrs.into(), item.into()) {
Ok(prog) => prog Ok(prog) => prog.expand(),
.expand() Err(err) => err.emit_as_expr_tokens(),
.unwrap_or_else(|err| abort!(err.span(), "{}", err))
.into(),
Err(err) => abort!(err.span(), "{}", err),
} }
.into()
} }
/// Marks a function as a raw tracepoint eBPF program that can be attached at a /// Marks a function as a raw tracepoint eBPF program that can be attached at a
@ -314,16 +273,13 @@ pub fn perf_event(attrs: TokenStream, item: TokenStream) -> TokenStream {
/// Ok(0) /// Ok(0)
/// } /// }
/// ``` /// ```
#[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn raw_tracepoint(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn raw_tracepoint(attrs: TokenStream, item: TokenStream) -> TokenStream {
match RawTracePoint::parse(attrs.into(), item.into()) { match RawTracePoint::parse(attrs.into(), item.into()) {
Ok(prog) => prog Ok(prog) => prog.expand(),
.expand() Err(err) => err.into_compile_error(),
.unwrap_or_else(|err| abort!(err.span(), "{}", err))
.into(),
Err(err) => abort!(err.span(), "{}", err),
} }
.into()
} }
/// Marks a function as an LSM program that can be attached to Linux LSM hooks. /// Marks a function as an LSM program that can be attached to Linux LSM hooks.
@ -361,16 +317,13 @@ pub fn raw_tracepoint(attrs: TokenStream, item: TokenStream) -> TokenStream {
/// Ok(0) /// Ok(0)
/// } /// }
/// ``` /// ```
#[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn lsm(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn lsm(attrs: TokenStream, item: TokenStream) -> TokenStream {
match Lsm::parse(attrs.into(), item.into()) { match Lsm::parse(attrs.into(), item.into()) {
Ok(prog) => prog Ok(prog) => prog.expand(),
.expand() Err(err) => err.into_compile_error(),
.unwrap_or_else(|err| abort!(err.span(), "{}", err))
.into(),
Err(err) => abort!(err.span(), "{}", err),
} }
.into()
} }
/// Marks a function as a [BTF-enabled raw tracepoint][1] eBPF program that can be attached at /// Marks a function as a [BTF-enabled raw tracepoint][1] eBPF program that can be attached at
@ -403,16 +356,13 @@ pub fn lsm(attrs: TokenStream, item: TokenStream) -> TokenStream {
/// ``` /// ```
/// ///
/// [1]: https://github.com/torvalds/linux/commit/9e15db66136a14cde3f35691f1d839d950118826 /// [1]: https://github.com/torvalds/linux/commit/9e15db66136a14cde3f35691f1d839d950118826
#[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn btf_tracepoint(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn btf_tracepoint(attrs: TokenStream, item: TokenStream) -> TokenStream {
match BtfTracePoint::parse(attrs.into(), item.into()) { match BtfTracePoint::parse(attrs.into(), item.into()) {
Ok(prog) => prog Ok(prog) => prog.expand(),
.expand() Err(err) => err.into_compile_error(),
.unwrap_or_else(|err| abort!(err.span(), "{}", err))
.into(),
Err(err) => abort!(err.span(), "{}", err),
} }
.into()
} }
/// Marks a function as a SK_SKB Stream Parser eBPF program that can be attached /// Marks a function as a SK_SKB Stream Parser eBPF program that can be attached
@ -440,7 +390,6 @@ pub fn btf_tracepoint(attrs: TokenStream, item: TokenStream) -> TokenStream {
/// Ok(ctx.len()) /// Ok(ctx.len())
///} ///}
/// ``` /// ```
#[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn stream_parser(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn stream_parser(attrs: TokenStream, item: TokenStream) -> TokenStream {
sk_skb(SkSkbKind::StreamParser, attrs, item) sk_skb(SkSkbKind::StreamParser, attrs, item)
@ -471,7 +420,6 @@ pub fn stream_parser(attrs: TokenStream, item: TokenStream) -> TokenStream {
/// Ok(sk_action::SK_PASS) /// Ok(sk_action::SK_PASS)
///} ///}
/// ``` /// ```
#[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn stream_verdict(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn stream_verdict(attrs: TokenStream, item: TokenStream) -> TokenStream {
sk_skb(SkSkbKind::StreamVerdict, attrs, item) sk_skb(SkSkbKind::StreamVerdict, attrs, item)
@ -479,12 +427,10 @@ pub fn stream_verdict(attrs: TokenStream, item: TokenStream) -> TokenStream {
fn sk_skb(kind: SkSkbKind, attrs: TokenStream, item: TokenStream) -> TokenStream { fn sk_skb(kind: SkSkbKind, attrs: TokenStream, item: TokenStream) -> TokenStream {
match SkSkb::parse(kind, attrs.into(), item.into()) { match SkSkb::parse(kind, attrs.into(), item.into()) {
Ok(prog) => prog Ok(prog) => prog.expand(),
.expand() Err(err) => err.emit_as_expr_tokens(),
.unwrap_or_else(|err| abort!(err.span(), "{}", err))
.into(),
Err(err) => abort!(err.span(), "{}", err),
} }
.into()
} }
/// Marks a function as a eBPF Socket Filter program that can be attached to /// Marks a function as a eBPF Socket Filter program that can be attached to
@ -504,16 +450,13 @@ fn sk_skb(kind: SkSkbKind, attrs: TokenStream, item: TokenStream) -> TokenStream
/// return 0 /// return 0
/// } /// }
/// ``` /// ```
#[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn socket_filter(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn socket_filter(attrs: TokenStream, item: TokenStream) -> TokenStream {
match SocketFilter::parse(attrs.into(), item.into()) { match SocketFilter::parse(attrs.into(), item.into()) {
Ok(prog) => prog Ok(prog) => prog.expand(),
.expand() Err(err) => err.emit_as_expr_tokens(),
.unwrap_or_else(|err| abort!(err.span(), "{}", err))
.into(),
Err(err) => abort!(err.span(), "{}", err),
} }
.into()
} }
/// Marks a function as a fentry eBPF program that can be attached to almost /// Marks a function as a fentry eBPF program that can be attached to almost
@ -548,16 +491,13 @@ pub fn socket_filter(attrs: TokenStream, item: TokenStream) -> TokenStream {
/// Ok(0) /// Ok(0)
/// } /// }
/// ``` /// ```
#[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn fentry(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn fentry(attrs: TokenStream, item: TokenStream) -> TokenStream {
match FEntry::parse(attrs.into(), item.into()) { match FEntry::parse(attrs.into(), item.into()) {
Ok(prog) => prog Ok(prog) => prog.expand(),
.expand() Err(err) => err.into_compile_error(),
.unwrap_or_else(|err| abort!(err.span(), "{}", err))
.into(),
Err(err) => abort!(err.span(), "{}", err),
} }
.into()
} }
/// Marks a function as a fexit eBPF program that can be attached to almost /// Marks a function as a fexit eBPF program that can be attached to almost
@ -593,16 +533,13 @@ pub fn fentry(attrs: TokenStream, item: TokenStream) -> TokenStream {
/// Ok(0) /// Ok(0)
/// } /// }
/// ``` /// ```
#[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn fexit(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn fexit(attrs: TokenStream, item: TokenStream) -> TokenStream {
match FExit::parse(attrs.into(), item.into()) { match FExit::parse(attrs.into(), item.into()) {
Ok(prog) => prog Ok(prog) => prog.expand(),
.expand() Err(err) => err.into_compile_error(),
.unwrap_or_else(|err| abort!(err.span(), "{}", err))
.into(),
Err(err) => abort!(err.span(), "{}", err),
} }
.into()
} }
/// Marks a function as an eBPF Socket Lookup program that can be attached to /// Marks a function as an eBPF Socket Lookup program that can be attached to
@ -623,16 +560,13 @@ pub fn fexit(attrs: TokenStream, item: TokenStream) -> TokenStream {
/// return 0 /// return 0
/// } /// }
/// ``` /// ```
#[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn sk_lookup(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn sk_lookup(attrs: TokenStream, item: TokenStream) -> TokenStream {
match SkLookup::parse(attrs.into(), item.into()) { match SkLookup::parse(attrs.into(), item.into()) {
Ok(prog) => prog Ok(prog) => prog.expand(),
.expand() Err(err) => err.emit_as_expr_tokens(),
.unwrap_or_else(|err| abort!(err.span(), "{}", err))
.into(),
Err(err) => abort!(err.span(), "{}", err),
} }
.into()
} }
/// Marks a function as a cgroup device eBPF program that can be attached to a /// Marks a function as a cgroup device eBPF program that can be attached to a
@ -656,14 +590,11 @@ pub fn sk_lookup(attrs: TokenStream, item: TokenStream) -> TokenStream {
/// return 0; /// return 0;
/// } /// }
/// ``` /// ```
#[proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn cgroup_device(attrs: TokenStream, item: TokenStream) -> TokenStream { pub fn cgroup_device(attrs: TokenStream, item: TokenStream) -> TokenStream {
match CgroupDevice::parse(attrs.into(), item.into()) { match CgroupDevice::parse(attrs.into(), item.into()) {
Ok(prog) => prog Ok(prog) => prog.expand(),
.expand() Err(err) => err.emit_as_expr_tokens(),
.unwrap_or_else(|err| abort!(err.span(), "{}", err))
.into(),
Err(err) => abort!(err.span(), "{}", err),
} }
.into()
} }

@ -13,41 +13,50 @@ pub(crate) struct Lsm {
} }
impl Lsm { impl Lsm {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Lsm> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self> {
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
let mut args = syn::parse2(attrs)?; let mut args = syn::parse2(attrs)?;
let hook = pop_string_arg(&mut args, "hook"); let hook = pop_string_arg(&mut args, "hook");
let sleepable = pop_bool_arg(&mut args, "sleepable"); let sleepable = pop_bool_arg(&mut args, "sleepable");
err_on_unknown_args(&args)?; err_on_unknown_args(&args)?;
Ok(Lsm { Ok(Self {
item, item,
hook, hook,
sleepable, sleepable,
}) })
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> TokenStream {
let section_prefix = if self.sleepable { "lsm.s" } else { "lsm" }; let Self {
let section_name: Cow<'_, _> = if let Some(hook) = &self.hook { item,
hook,
sleepable,
} = self;
let ItemFn {
attrs: _,
vis,
sig,
block: _,
} = item;
let section_prefix = if *sleepable { "lsm.s" } else { "lsm" };
let section_name: Cow<'_, _> = if let Some(hook) = hook {
format!("{}/{}", section_prefix, hook).into() format!("{}/{}", section_prefix, hook).into()
} else { } else {
section_prefix.into() section_prefix.into()
}; };
let fn_vis = &self.item.vis;
let fn_name = self.item.sig.ident.clone();
let item = &self.item;
// LSM probes need to return an integer corresponding to the correct // LSM probes need to return an integer corresponding to the correct
// policy decision. Therefore we do not simply default to a return value // policy decision. Therefore we do not simply default to a return value
// of 0 as in other program types. // of 0 as in other program types.
Ok(quote! { let fn_name = &sig.ident;
quote! {
#[no_mangle] #[no_mangle]
#[link_section = #section_name] #[link_section = #section_name]
#fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> i32 { #vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> i32 {
return #fn_name(::aya_ebpf::programs::LsmContext::new(ctx)); return #fn_name(::aya_ebpf::programs::LsmContext::new(ctx));
#item #item
} }
}) }
} }
} }
@ -71,7 +80,7 @@ mod tests {
}, },
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "lsm.s/bprm_committed_creds"] #[link_section = "lsm.s/bprm_committed_creds"]
@ -99,7 +108,7 @@ mod tests {
}, },
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "lsm/bprm_committed_creds"] #[link_section = "lsm/bprm_committed_creds"]

@ -15,18 +15,18 @@ impl Map {
let item: ItemStatic = syn::parse2(item)?; let item: ItemStatic = syn::parse2(item)?;
let mut args = syn::parse2(attrs)?; let mut args = syn::parse2(attrs)?;
let name = name_arg(&mut args).unwrap_or_else(|| item.ident.to_string()); let name = name_arg(&mut args).unwrap_or_else(|| item.ident.to_string());
Ok(Map { item, name }) Ok(Self { item, name })
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> TokenStream {
let section_name: Cow<'_, _> = "maps".to_string().into(); let section_name: Cow<'_, _> = "maps".into();
let name = &self.name; let name = &self.name;
let item = &self.item; let item = &self.item;
Ok(quote! { quote! {
#[link_section = #section_name] #[link_section = #section_name]
#[export_name = #name] #[export_name = #name]
#item #item
}) }
} }
} }
@ -45,7 +45,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = map.expand().unwrap(); let expanded = map.expand();
let expected = quote!( let expected = quote!(
#[link_section = "maps"] #[link_section = "maps"]
#[export_name = "foo"] #[export_name = "foo"]
@ -63,7 +63,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = map.expand().unwrap(); let expanded = map.expand();
let expected = quote!( let expected = quote!(
#[link_section = "maps"] #[link_section = "maps"]
#[export_name = "BAR"] #[export_name = "BAR"]

@ -1,35 +1,40 @@
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use proc_macro_error::abort; use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _};
use quote::quote; use quote::quote;
use syn::{ItemFn, Result}; use syn::{spanned::Spanned as _, ItemFn};
pub(crate) struct PerfEvent { pub(crate) struct PerfEvent {
item: ItemFn, item: ItemFn,
} }
impl PerfEvent { impl PerfEvent {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self, Diagnostic> {
if !attrs.is_empty() { if !attrs.is_empty() {
abort!(attrs, "unexpected attribute") return Err(attrs.span().error("unexpected attribute"));
} }
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
Ok(PerfEvent { item }) Ok(Self { item })
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> TokenStream {
let fn_vis = &self.item.vis; let Self { item } = self;
let fn_name = self.item.sig.ident.clone(); let ItemFn {
let item = &self.item; attrs: _,
Ok(quote! { vis,
sig,
block: _,
} = item;
let fn_name = &sig.ident;
quote! {
#[no_mangle] #[no_mangle]
#[link_section = "perf_event"] #[link_section = "perf_event"]
#fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> u32 { #vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> u32 {
let _ = #fn_name(::aya_ebpf::programs::PerfEventContext::new(ctx)); let _ = #fn_name(::aya_ebpf::programs::PerfEventContext::new(ctx));
return 0; return 0;
#item #item
} }
}) }
} }
} }
@ -50,7 +55,7 @@ mod tests {
), ),
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "perf_event"] #[link_section = "perf_event"]

@ -12,33 +12,38 @@ pub(crate) struct RawTracePoint {
} }
impl RawTracePoint { impl RawTracePoint {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<RawTracePoint> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self> {
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
let mut args = syn::parse2(attrs)?; let mut args = syn::parse2(attrs)?;
let tracepoint = pop_string_arg(&mut args, "tracepoint"); let tracepoint = pop_string_arg(&mut args, "tracepoint");
err_on_unknown_args(&args)?; err_on_unknown_args(&args)?;
Ok(RawTracePoint { item, tracepoint }) Ok(Self { item, tracepoint })
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> TokenStream {
let section_name: Cow<'_, _> = if let Some(tracepoint) = &self.tracepoint { let Self { item, tracepoint } = self;
let ItemFn {
attrs: _,
vis,
sig,
block: _,
} = item;
let section_name: Cow<'_, _> = if let Some(tracepoint) = tracepoint {
format!("raw_tp/{}", tracepoint).into() format!("raw_tp/{}", tracepoint).into()
} else { } else {
"raw_tp".into() "raw_tp".into()
}; };
let fn_vis = &self.item.vis; let fn_name = &sig.ident;
let fn_name = self.item.sig.ident.clone(); quote! {
let item = &self.item;
Ok(quote! {
#[no_mangle] #[no_mangle]
#[link_section = #section_name] #[link_section = #section_name]
#fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> u32 { #vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> u32 {
let _ = #fn_name(::aya_ebpf::programs::RawTracePointContext::new(ctx)); let _ = #fn_name(::aya_ebpf::programs::RawTracePointContext::new(ctx));
return 0; return 0;
#item #item
} }
}) }
} }
} }
@ -59,7 +64,7 @@ mod tests {
}, },
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "raw_tp/sys_enter"] #[link_section = "raw_tp/sys_enter"]

@ -1,34 +1,39 @@
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use proc_macro_error::abort; use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _};
use quote::quote; use quote::quote;
use syn::{ItemFn, Result}; use syn::{spanned::Spanned as _, ItemFn};
pub(crate) struct SkLookup { pub(crate) struct SkLookup {
item: ItemFn, item: ItemFn,
} }
impl SkLookup { impl SkLookup {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self, Diagnostic> {
if !attrs.is_empty() { if !attrs.is_empty() {
abort!(attrs, "unexpected attribute") return Err(attrs.span().error("unexpected attribute"));
} }
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
Ok(SkLookup { item }) Ok(Self { item })
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> TokenStream {
let fn_name = self.item.sig.ident.clone(); let Self { item } = self;
let fn_vis = &self.item.vis; let ItemFn {
let item = &self.item; attrs: _,
Ok(quote! { vis,
sig,
block: _,
} = item;
let fn_name = &sig.ident;
quote! {
#[no_mangle] #[no_mangle]
#[link_section = "sk_lookup"] #[link_section = "sk_lookup"]
#fn_vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::bpf_sk_lookup) -> u32 { #vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::bpf_sk_lookup) -> u32 {
return #fn_name(::aya_ebpf::programs::SkLookupContext::new(ctx)); return #fn_name(::aya_ebpf::programs::SkLookupContext::new(ctx));
#item #item
} }
}) }
} }
} }
@ -49,7 +54,7 @@ mod tests {
}, },
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "sk_lookup"] #[link_section = "sk_lookup"]

@ -1,34 +1,39 @@
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use proc_macro_error::abort; use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _};
use quote::quote; use quote::quote;
use syn::{ItemFn, Result}; use syn::{spanned::Spanned as _, ItemFn};
pub(crate) struct SkMsg { pub(crate) struct SkMsg {
item: ItemFn, item: ItemFn,
} }
impl SkMsg { impl SkMsg {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self, Diagnostic> {
if !attrs.is_empty() { if !attrs.is_empty() {
abort!(attrs, "unexpected attribute") return Err(attrs.span().error("unexpected attribute"));
} }
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
Ok(SkMsg { item }) Ok(Self { item })
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> TokenStream {
let fn_vis = &self.item.vis; let Self { item } = self;
let fn_name = self.item.sig.ident.clone(); let ItemFn {
let item = &self.item; attrs: _,
Ok(quote! { vis,
sig,
block: _,
} = item;
let fn_name = &sig.ident;
quote! {
#[no_mangle] #[no_mangle]
#[link_section = "sk_msg"] #[link_section = "sk_msg"]
#fn_vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::sk_msg_md) -> u32 { #vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::sk_msg_md) -> u32 {
return #fn_name(::aya_ebpf::programs::SkMsgContext::new(ctx)); return #fn_name(::aya_ebpf::programs::SkMsgContext::new(ctx));
#item #item
} }
}) }
} }
} }
@ -49,7 +54,7 @@ mod tests {
}, },
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "sk_msg"] #[link_section = "sk_msg"]

@ -1,9 +1,9 @@
use std::borrow::Cow; use std::borrow::Cow;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use proc_macro_error::abort; use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _};
use quote::quote; use quote::quote;
use syn::{ItemFn, Result}; use syn::{spanned::Spanned as _, ItemFn};
#[allow(clippy::enum_variant_names)] #[allow(clippy::enum_variant_names)]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
@ -28,29 +28,37 @@ pub(crate) struct SkSkb {
} }
impl SkSkb { impl SkSkb {
pub(crate) fn parse(kind: SkSkbKind, attrs: TokenStream, item: TokenStream) -> Result<SkSkb> { pub(crate) fn parse(
kind: SkSkbKind,
attrs: TokenStream,
item: TokenStream,
) -> Result<Self, Diagnostic> {
if !attrs.is_empty() { if !attrs.is_empty() {
abort!(attrs, "unexpected attribute"); return Err(attrs.span().error("unexpected attribute"));
} }
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
Ok(SkSkb { item, kind }) Ok(Self { item, kind })
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> TokenStream {
let kind = &self.kind; let Self { kind, item } = self;
let ItemFn {
attrs: _,
vis,
sig,
block: _,
} = item;
let section_name: Cow<'_, _> = format!("sk_skb/{kind}").into(); let section_name: Cow<'_, _> = format!("sk_skb/{kind}").into();
let fn_name = self.item.sig.ident.clone(); let fn_name = &sig.ident;
let fn_vis = &self.item.vis; quote! {
let item = &self.item;
Ok(quote! {
#[no_mangle] #[no_mangle]
#[link_section = #section_name] #[link_section = #section_name]
#fn_vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::__sk_buff) -> u32 { #vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::__sk_buff) -> u32 {
return #fn_name(::aya_ebpf::programs::SkBuffContext::new(ctx)); return #fn_name(::aya_ebpf::programs::SkBuffContext::new(ctx));
#item #item
} }
}) }
} }
} }
@ -72,7 +80,7 @@ mod tests {
}, },
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "sk_skb/stream_parser"] #[link_section = "sk_skb/stream_parser"]
@ -99,7 +107,7 @@ mod tests {
}, },
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "sk_skb/stream_verdict"] #[link_section = "sk_skb/stream_verdict"]

@ -1,34 +1,39 @@
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use proc_macro_error::abort; use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _};
use quote::quote; use quote::quote;
use syn::{ItemFn, Result}; use syn::{spanned::Spanned as _, ItemFn};
pub(crate) struct SockOps { pub(crate) struct SockOps {
item: ItemFn, item: ItemFn,
} }
impl SockOps { impl SockOps {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self, Diagnostic> {
if !attrs.is_empty() { if !attrs.is_empty() {
abort!(attrs, "unexpected attribute") return Err(attrs.span().error("unexpected attribute"));
} }
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
Ok(SockOps { item }) Ok(Self { item })
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> TokenStream {
let fn_vis = &self.item.vis; let Self { item } = self;
let fn_name = self.item.sig.ident.clone(); let ItemFn {
let item = &self.item; attrs: _,
Ok(quote! { vis,
sig,
block: _,
} = item;
let fn_name = &sig.ident;
quote! {
#[no_mangle] #[no_mangle]
#[link_section = "sockops"] #[link_section = "sockops"]
#fn_vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::bpf_sock_ops) -> u32 { #vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::bpf_sock_ops) -> u32 {
return #fn_name(::aya_ebpf::programs::SockOpsContext::new(ctx)); return #fn_name(::aya_ebpf::programs::SockOpsContext::new(ctx));
#item #item
} }
}) }
} }
} }
@ -49,7 +54,7 @@ mod tests {
}, },
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "sockops"] #[link_section = "sockops"]

@ -1,34 +1,39 @@
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use proc_macro_error::abort; use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _};
use quote::quote; use quote::quote;
use syn::{ItemFn, Result}; use syn::{spanned::Spanned as _, ItemFn};
pub(crate) struct SocketFilter { pub(crate) struct SocketFilter {
item: ItemFn, item: ItemFn,
} }
impl SocketFilter { impl SocketFilter {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self, Diagnostic> {
if !attrs.is_empty() { if !attrs.is_empty() {
abort!(attrs, "unexpected attribute") return Err(attrs.span().error("unexpected attribute"));
} }
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
Ok(SocketFilter { item }) Ok(Self { item })
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> TokenStream {
let fn_name = self.item.sig.ident.clone(); let Self { item } = self;
let fn_vis = &self.item.vis; let ItemFn {
let item = &self.item; attrs: _,
Ok(quote! { vis,
sig,
block: _,
} = item;
let fn_name = &sig.ident;
quote! {
#[no_mangle] #[no_mangle]
#[link_section = "socket"] #[link_section = "socket"]
#fn_vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::__sk_buff) -> i64 { #vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::__sk_buff) -> i64 {
return #fn_name(::aya_ebpf::programs::SkBuffContext::new(ctx)); return #fn_name(::aya_ebpf::programs::SkBuffContext::new(ctx));
#item #item
} }
}) }
} }
} }
@ -49,7 +54,7 @@ mod tests {
}, },
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "socket"] #[link_section = "socket"]

@ -1,34 +1,39 @@
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use proc_macro_error::abort; use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _};
use quote::quote; use quote::quote;
use syn::{ItemFn, Result}; use syn::{spanned::Spanned as _, ItemFn};
pub(crate) struct SchedClassifier { pub(crate) struct SchedClassifier {
item: ItemFn, item: ItemFn,
} }
impl SchedClassifier { impl SchedClassifier {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self, Diagnostic> {
if !attrs.is_empty() { if !attrs.is_empty() {
abort!(attrs, "unexpected attribute") return Err(attrs.span().error("unexpected attribute"));
} }
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
Ok(SchedClassifier { item }) Ok(Self { item })
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> TokenStream {
let fn_vis = &self.item.vis; let Self { item } = self;
let fn_name = self.item.sig.ident.clone(); let ItemFn {
let item = &self.item; attrs: _,
Ok(quote! { vis,
sig,
block: _,
} = item;
let fn_name = &sig.ident;
quote! {
#[no_mangle] #[no_mangle]
#[link_section = "classifier"] #[link_section = "classifier"]
#fn_vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::__sk_buff) -> i32 { #vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::__sk_buff) -> i32 {
return #fn_name(::aya_ebpf::programs::TcContext::new(ctx)); return #fn_name(::aya_ebpf::programs::TcContext::new(ctx));
#item #item
} }
}) }
} }
} }
@ -49,7 +54,7 @@ mod tests {
}, },
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "classifier"] #[link_section = "classifier"]

@ -1,52 +1,64 @@
use std::borrow::Cow; use std::borrow::Cow;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use proc_macro_error::abort; use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _};
use quote::quote; use quote::quote;
use syn::{ItemFn, Result}; use syn::{spanned::Spanned as _, ItemFn};
use crate::args::{err_on_unknown_args, pop_string_arg}; use crate::args::{err_on_unknown_args, pop_string_arg};
pub(crate) struct TracePoint { pub(crate) struct TracePoint {
item: ItemFn, item: ItemFn,
category: Option<String>, name_and_category: Option<(String, String)>,
name: Option<String>,
} }
impl TracePoint { impl TracePoint {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<TracePoint> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self, Diagnostic> {
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
let span = attrs.span();
let mut args = syn::parse2(attrs)?; let mut args = syn::parse2(attrs)?;
let name = pop_string_arg(&mut args, "name"); let name = pop_string_arg(&mut args, "name");
let category = pop_string_arg(&mut args, "category"); let category = pop_string_arg(&mut args, "category");
err_on_unknown_args(&args)?; err_on_unknown_args(&args)?;
Ok(TracePoint { match (name, category) {
item, (None, None) => Ok(Self {
category, item,
name, name_and_category: None,
}) }),
(Some(name), Some(category)) => Ok(Self {
item,
name_and_category: Some((name, category)),
}),
_ => Err(span.error("expected `name` and `category` arguments")),
}
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> TokenStream {
let section_name: Cow<'_, _> = match (&self.category, &self.name) { let Self {
(Some(category), Some(name)) => format!("tracepoint/{}/{}", category, name).into(), item,
(Some(_), None) => abort!(self.item, "expected `name` and `category` arguments"), name_and_category,
(None, Some(_)) => abort!(self.item, "expected `name` and `category` arguments"), } = self;
_ => "tracepoint".into(), let section_name: Cow<'_, _> = match name_and_category {
Some((name, category)) => format!("tracepoint/{category}/{name}").into(),
None => "tracepoint".into(),
}; };
let fn_vis = &self.item.vis; let ItemFn {
let fn_name = self.item.sig.ident.clone(); attrs: _,
let item = &self.item; vis,
Ok(quote! { sig,
block: _,
} = item;
let fn_name = &sig.ident;
quote! {
#[no_mangle] #[no_mangle]
#[link_section = #section_name] #[link_section = #section_name]
#fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> u32 { #vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> u32 {
let _ = #fn_name(::aya_ebpf::programs::TracePointContext::new(ctx)); let _ = #fn_name(::aya_ebpf::programs::TracePointContext::new(ctx));
return 0; return 0;
#item #item
} }
}) }
} }
} }
@ -67,7 +79,7 @@ mod tests {
}, },
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "tracepoint/syscalls/sys_enter_bind"] #[link_section = "tracepoint/syscalls/sys_enter_bind"]

@ -1,9 +1,9 @@
use std::borrow::Cow; use std::borrow::Cow;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use proc_macro_error::abort; use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _};
use quote::quote; use quote::quote;
use syn::{ItemFn, Result}; use syn::{spanned::Spanned as _, ItemFn};
use crate::args::{err_on_unknown_args, pop_bool_arg, pop_string_arg}; use crate::args::{err_on_unknown_args, pop_bool_arg, pop_string_arg};
@ -34,15 +34,24 @@ pub(crate) struct UProbe {
} }
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<Self, Diagnostic> {
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
let span = attrs.span();
let mut args = syn::parse2(attrs)?; let mut args = syn::parse2(attrs)?;
let path = pop_string_arg(&mut args, "path"); let path = pop_string_arg(&mut args, "path");
let function = pop_string_arg(&mut args, "function"); let function = pop_string_arg(&mut args, "function");
let offset = pop_string_arg(&mut args, "offset").map(|v| v.parse::<u64>().unwrap()); let offset = pop_string_arg(&mut args, "offset")
.as_deref()
.map(str::parse)
.transpose()
.map_err(|err| span.error(format!("failed to parse `offset` argument: {}", err)))?;
let sleepable = pop_bool_arg(&mut args, "sleepable"); let sleepable = pop_bool_arg(&mut args, "sleepable");
err_on_unknown_args(&args)?; err_on_unknown_args(&args)?;
Ok(UProbe { Ok(Self {
kind, kind,
item, item,
path, path,
@ -52,39 +61,38 @@ impl UProbe {
}) })
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> Result<TokenStream, Diagnostic> {
let prefix = if self.sleepable { let Self {
format!("{}.s", self.kind) kind,
} else { path,
format!("{}", self.kind) function,
}; offset,
let section_name: Cow<'_, _> = if self.path.is_some() && self.offset.is_some() { item,
if self.function.is_none() { sleepable,
abort!(self.item.sig.ident, "expected `function` attribute"); } = self;
} let ItemFn {
let mut path = self.path.as_ref().unwrap().clone(); attrs: _,
if path.starts_with('/') { vis,
path.remove(0); sig,
} block: _,
format!( } = item;
"{}/{}:{}+{}", let mut prefix = kind.to_string();
prefix, if *sleepable {
path, prefix.push_str(".s");
self.function.as_ref().unwrap(), }
self.offset.unwrap() let section_name: Cow<'_, _> = match path {
) None => prefix.into(),
.into() Some(path) => {
} else if self.path.is_some() { let path = path.strip_prefix("/").unwrap_or(path);
if self.function.is_none() { // TODO: check this in parse instead.
abort!(self.item.sig.ident, "expected `function` attribute"); let function = function
} .as_deref()
let mut path = self.path.as_ref().unwrap().clone(); .ok_or(item.sig.span().error("expected `function` attribute"))?;
if path.starts_with('/') { match offset {
path.remove(0); None => format!("{prefix}/{path}:{function}").into(),
Some(offset) => format!("{prefix}/{path}:{function}+{offset}",).into(),
}
} }
format!("{}/{}:{}", prefix, path, self.function.as_ref().unwrap()).into()
} else {
prefix.to_string().into()
}; };
let probe_type = if section_name.as_ref().starts_with("uprobe") { let probe_type = if section_name.as_ref().starts_with("uprobe") {
@ -92,13 +100,11 @@ impl UProbe {
} else { } else {
quote! { RetProbeContext } quote! { RetProbeContext }
}; };
let fn_vis = &self.item.vis; let fn_name = &sig.ident;
let fn_name = self.item.sig.ident.clone();
let item = &self.item;
Ok(quote! { Ok(quote! {
#[no_mangle] #[no_mangle]
#[link_section = #section_name] #[link_section = #section_name]
#fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> u32 { #vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> u32 {
let _ = #fn_name(::aya_ebpf::programs::#probe_type::new(ctx)); let _ = #fn_name(::aya_ebpf::programs::#probe_type::new(ctx));
return 0; return 0;

@ -1,6 +1,7 @@
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _};
use quote::quote; use quote::quote;
use syn::{Error, ItemFn, Result}; use syn::{spanned::Spanned as _, ItemFn};
use crate::args::{err_on_unknown_args, pop_bool_arg, pop_string_arg, Args}; use crate::args::{err_on_unknown_args, pop_bool_arg, pop_string_arg, Args};
@ -17,8 +18,9 @@ pub(crate) enum XdpMap {
} }
impl Xdp { impl Xdp {
pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Xdp> { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self, Diagnostic> {
let item = syn::parse2(item)?; let item = syn::parse2(item)?;
let span = attrs.span();
let mut args: Args = syn::parse2(attrs)?; let mut args: Args = syn::parse2(attrs)?;
let frags = pop_bool_arg(&mut args, "frags"); let frags = pop_bool_arg(&mut args, "frags");
@ -26,39 +28,42 @@ impl Xdp {
Some("cpumap") => Some(XdpMap::CpuMap), Some("cpumap") => Some(XdpMap::CpuMap),
Some("devmap") => Some(XdpMap::DevMap), Some("devmap") => Some(XdpMap::DevMap),
Some(name) => { Some(name) => {
return Err(Error::new_spanned( return Err(span.error(format!(
"map", "Invalid value. Expected 'cpumap' or 'devmap', found '{name}'"
format!("Invalid value. Expected 'cpumap' or 'devmap', found '{name}'"), )))
))
} }
None => None, None => None,
}; };
err_on_unknown_args(&args)?; err_on_unknown_args(&args)?;
Ok(Xdp { item, frags, map }) Ok(Self { item, frags, map })
} }
pub(crate) fn expand(&self) -> Result<TokenStream> { pub(crate) fn expand(&self) -> TokenStream {
let mut section_name = vec![if self.frags { "xdp.frags" } else { "xdp" }]; let Self { item, frags, map } = self;
match self.map { let ItemFn {
attrs: _,
vis,
sig,
block: _,
} = item;
let mut section_name = vec![if *frags { "xdp.frags" } else { "xdp" }];
match map {
Some(XdpMap::CpuMap) => section_name.push("cpumap"), Some(XdpMap::CpuMap) => section_name.push("cpumap"),
Some(XdpMap::DevMap) => section_name.push("devmap"), Some(XdpMap::DevMap) => section_name.push("devmap"),
None => (), None => (),
}; };
let section_name = section_name.join("/"); let section_name = section_name.join("/");
let fn_name = &sig.ident;
let fn_vis = &self.item.vis; quote! {
let fn_name = self.item.sig.ident.clone();
let item = &self.item;
Ok(quote! {
#[no_mangle] #[no_mangle]
#[link_section = #section_name] #[link_section = #section_name]
#fn_vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::xdp_md) -> u32 { #vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::xdp_md) -> u32 {
return #fn_name(::aya_ebpf::programs::XdpContext::new(ctx)); return #fn_name(::aya_ebpf::programs::XdpContext::new(ctx));
#item #item
} }
}) }
} }
} }
@ -79,7 +84,7 @@ mod tests {
}, },
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "xdp"] #[link_section = "xdp"]
@ -105,7 +110,7 @@ mod tests {
}, },
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "xdp.frags"] #[link_section = "xdp.frags"]
@ -131,7 +136,7 @@ mod tests {
}, },
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "xdp/cpumap"] #[link_section = "xdp/cpumap"]
@ -157,7 +162,7 @@ mod tests {
}, },
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "xdp/devmap"] #[link_section = "xdp/devmap"]
@ -197,7 +202,7 @@ mod tests {
}, },
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "xdp.frags/cpumap"] #[link_section = "xdp.frags/cpumap"]
@ -223,7 +228,7 @@ mod tests {
}, },
) )
.unwrap(); .unwrap();
let expanded = prog.expand().unwrap(); let expanded = prog.expand();
let expected = quote! { let expected = quote! {
#[no_mangle] #[no_mangle]
#[link_section = "xdp.frags/devmap"] #[link_section = "xdp.frags/devmap"]

Loading…
Cancel
Save