From 5a43bedc0180ba41854e6c23f0476c2cbeb1e2bd Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Mon, 2 Dec 2024 11:20:04 -0500 Subject: [PATCH] Replace proc-macro-error with proc-macro2-diagnostics proc-macro-error is unmaintained. --- Cargo.toml | 2 +- aya-ebpf-macros/Cargo.toml | 2 +- aya-ebpf-macros/src/btf_tracepoint.rs | 27 +-- aya-ebpf-macros/src/cgroup_device.rs | 31 ++-- aya-ebpf-macros/src/cgroup_skb.rs | 62 ++++--- aya-ebpf-macros/src/cgroup_sock.rs | 53 +++--- aya-ebpf-macros/src/cgroup_sock_addr.rs | 79 ++++---- aya-ebpf-macros/src/cgroup_sockopt.rs | 48 ++--- aya-ebpf-macros/src/cgroup_sysctl.rs | 31 ++-- aya-ebpf-macros/src/fentry.rs | 37 ++-- aya-ebpf-macros/src/fexit.rs | 37 ++-- aya-ebpf-macros/src/kprobe.rs | 69 ++++--- aya-ebpf-macros/src/lib.rs | 233 +++++++++--------------- aya-ebpf-macros/src/lsm.rs | 35 ++-- aya-ebpf-macros/src/map.rs | 14 +- aya-ebpf-macros/src/perf_event.rs | 31 ++-- aya-ebpf-macros/src/raw_tracepoint.rs | 27 +-- aya-ebpf-macros/src/sk_lookup.rs | 31 ++-- aya-ebpf-macros/src/sk_msg.rs | 31 ++-- aya-ebpf-macros/src/sk_skb.rs | 38 ++-- aya-ebpf-macros/src/sock_ops.rs | 31 ++-- aya-ebpf-macros/src/socket_filter.rs | 31 ++-- aya-ebpf-macros/src/tc.rs | 31 ++-- aya-ebpf-macros/src/tracepoint.rs | 58 +++--- aya-ebpf-macros/src/uprobe.rs | 88 ++++----- aya-ebpf-macros/src/xdp.rs | 51 +++--- 26 files changed, 642 insertions(+), 566 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 02f6db9dc..676910145 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,8 +81,8 @@ nix = { version = "0.29.0", default-features = false } num_enum = { version = "0.7", default-features = false } object = { version = "0.36", 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-diagnostics = { version = "0.10.1", default-features = false } public-api = { version = "0.42.0", default-features = false } quote = { version = "1", default-features = false } rand = { version = "0.8", default-features = false } diff --git a/aya-ebpf-macros/Cargo.toml b/aya-ebpf-macros/Cargo.toml index 88817a24c..e4a64b8bb 100644 --- a/aya-ebpf-macros/Cargo.toml +++ b/aya-ebpf-macros/Cargo.toml @@ -13,7 +13,7 @@ proc-macro = true [dependencies] proc-macro2 = { workspace = true } -proc-macro-error = { workspace = true } +proc-macro2-diagnostics = { workspace = true } quote = { workspace = true } syn = { workspace = true, default-features = true, features = ["full"] } diff --git a/aya-ebpf-macros/src/btf_tracepoint.rs b/aya-ebpf-macros/src/btf_tracepoint.rs index f9e23e0a2..da9f280de 100644 --- a/aya-ebpf-macros/src/btf_tracepoint.rs +++ b/aya-ebpf-macros/src/btf_tracepoint.rs @@ -18,28 +18,33 @@ impl BtfTracePoint { let function = pop_string_arg(&mut args, "function"); err_on_unknown_args(&args)?; - Ok(BtfTracePoint { item, function }) + Ok(Self { item, function }) } - pub(crate) fn expand(&self) -> Result { - let section_name: Cow<'_, _> = if let Some(function) = &self.function { + pub(crate) fn expand(&self) -> TokenStream { + 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() } else { "tp_btf".into() }; - let fn_vis = &self.item.vis; - let fn_name = self.item.sig.ident.clone(); - let item = &self.item; - Ok(quote! { + let fn_name = &sig.ident; + quote! { #[no_mangle] #[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)); return 0; #item } - }) + } } } @@ -60,7 +65,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote!( #[no_mangle] #[link_section = "tp_btf"] @@ -87,7 +92,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote!( #[no_mangle] #[link_section = "tp_btf/some_func"] diff --git a/aya-ebpf-macros/src/cgroup_device.rs b/aya-ebpf-macros/src/cgroup_device.rs index 28800cce6..4e2f9b65e 100644 --- a/aya-ebpf-macros/src/cgroup_device.rs +++ b/aya-ebpf-macros/src/cgroup_device.rs @@ -1,34 +1,39 @@ use proc_macro2::TokenStream; -use proc_macro_error::abort; +use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _}; use quote::quote; -use syn::{ItemFn, Result}; +use syn::{spanned::Spanned as _, ItemFn}; pub(crate) struct CgroupDevice { item: ItemFn, } impl CgroupDevice { - pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { + pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { if !attrs.is_empty() { - abort!(attrs, "unexpected attribute") + return Err(attrs.span().error("unexpected attribute")); } let item = syn::parse2(item)?; - Ok(CgroupDevice { item }) + Ok(Self { item }) } - pub(crate) fn expand(&self) -> Result { - let fn_vis = &self.item.vis; - let fn_name = self.item.sig.ident.clone(); - let item = &self.item; - Ok(quote! { + pub(crate) fn expand(&self) -> TokenStream { + let Self { item } = self; + let ItemFn { + attrs: _, + vis, + sig, + block: _, + } = item; + let fn_name = &sig.ident; + quote! { #[no_mangle] #[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)); #item } - }) + } } } @@ -49,7 +54,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "cgroup/dev"] diff --git a/aya-ebpf-macros/src/cgroup_skb.rs b/aya-ebpf-macros/src/cgroup_skb.rs index 39f60be1d..357d77d74 100644 --- a/aya-ebpf-macros/src/cgroup_skb.rs +++ b/aya-ebpf-macros/src/cgroup_skb.rs @@ -1,48 +1,52 @@ use std::borrow::Cow; use proc_macro2::TokenStream; -use proc_macro_error::abort; +use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _}; use quote::quote; -use syn::{Ident, ItemFn, Result}; +use syn::{Ident, ItemFn}; pub(crate) struct CgroupSkb { item: ItemFn, - attach_type: Option, + attach_type: Option, } impl CgroupSkb { - pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { + pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { let item: ItemFn = syn::parse2(item)?; - let mut attach_type = None; - if !attrs.is_empty() { + let attach_type = if attrs.is_empty() { + None + } else { let ident: Ident = syn::parse2(attrs)?; - match ident.to_string().as_str() { - "ingress" | "egress" => (), - _ => abort!(ident, "invalid attach type"), + if ident != "ingress" && ident != "egress" { + return Err(ident.span().error("invalid attach type")); } - attach_type = Some(ident.to_string()); - } - Ok(CgroupSkb { item, attach_type }) + Some(ident) + }; + Ok(Self { item, attach_type }) } - pub(crate) fn expand(&self) -> Result { - let section_name: Cow<'_, _> = if self.attach_type.is_some() { - format!("cgroup_skb/{}", self.attach_type.as_ref().unwrap()).into() - } else { - "cgroup/skb".into() + pub(crate) fn expand(&self) -> TokenStream { + let Self { item, attach_type } = self; + let ItemFn { + attrs: _, + 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 = self.item.sig.ident.clone(); - let item = &self.item; - Ok(quote! { + let fn_name = &sig.ident; + quote! { #[no_mangle] #[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)); #item } - }) + } } } @@ -63,7 +67,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "cgroup/skb"] @@ -89,7 +93,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "cgroup_skb/egress"] @@ -115,7 +119,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "cgroup_skb/ingress"] @@ -141,7 +145,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "cgroup_skb/egress"] @@ -167,7 +171,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "cgroup_skb/egress"] @@ -193,7 +197,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "cgroup_skb/egress"] diff --git a/aya-ebpf-macros/src/cgroup_sock.rs b/aya-ebpf-macros/src/cgroup_sock.rs index d8950500b..29f443f21 100644 --- a/aya-ebpf-macros/src/cgroup_sock.rs +++ b/aya-ebpf-macros/src/cgroup_sock.rs @@ -1,46 +1,51 @@ use std::borrow::Cow; use proc_macro2::TokenStream; -use proc_macro_error::abort; +use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _}; use quote::quote; -use syn::{Ident, ItemFn, Result}; +use syn::{spanned::Spanned as _, Ident, ItemFn}; pub(crate) struct CgroupSock { item: ItemFn, - attach_type: String, + attach_type: Ident, } impl CgroupSock { - pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { + pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { if attrs.is_empty() { - abort!(attrs, "missing attach type") + return Err(attrs.span().error("missing attach type")); } let item: ItemFn = syn::parse2(item)?; let attach_type: Ident = syn::parse2(attrs)?; - match attach_type.to_string().as_str() { - "post_bind4" | "post_bind6" | "sock_create" | "sock_release" => (), - _ => abort!(attach_type, "invalid attach type"), + if attach_type != "post_bind4" + && attach_type != "post_bind6" + && attach_type != "sock_create" + && attach_type != "sock_release" + { + return Err(attach_type.span().error("invalid attach type")); } - Ok(CgroupSock { - item, - attach_type: attach_type.to_string(), - }) + Ok(Self { item, attach_type }) } - pub(crate) fn expand(&self) -> Result { - let section_name: Cow<'_, _> = format!("cgroup/{}", self.attach_type).into(); - let fn_vis = &self.item.vis; - let fn_name = self.item.sig.ident.clone(); - let item = &self.item; - Ok(quote! { + pub(crate) fn expand(&self) -> TokenStream { + let Self { item, attach_type } = self; + let ItemFn { + attrs: _, + vis, + sig, + block: _, + } = item; + let section_name: Cow<'_, _> = format!("cgroup/{attach_type}").into(); + let fn_name = &sig.ident; + quote! { #[no_mangle] #[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)); #item } - }) + } } } @@ -61,7 +66,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "cgroup/post_bind4"] @@ -87,7 +92,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "cgroup/post_bind6"] @@ -112,7 +117,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "cgroup/sock_create"] @@ -137,7 +142,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "cgroup/sock_release"] diff --git a/aya-ebpf-macros/src/cgroup_sock_addr.rs b/aya-ebpf-macros/src/cgroup_sock_addr.rs index 17d0de399..55cc4b2ff 100644 --- a/aya-ebpf-macros/src/cgroup_sock_addr.rs +++ b/aya-ebpf-macros/src/cgroup_sock_addr.rs @@ -1,48 +1,59 @@ use std::borrow::Cow; use proc_macro2::TokenStream; -use proc_macro_error::abort; +use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _}; use quote::quote; -use syn::{Ident, ItemFn, Result}; +use syn::{spanned::Spanned as _, Ident, ItemFn}; pub(crate) struct CgroupSockAddr { item: ItemFn, - attach_type: String, + attach_type: Ident, } impl CgroupSockAddr { - pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { + pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { if attrs.is_empty() { - abort!(attrs, "missing attach type") + return Err(attrs.span().error("missing attach type")); } let item = syn::parse2(item)?; let attach_type: Ident = syn::parse2(attrs)?; - match attach_type.to_string().as_str() { - "connect4" | "connect6" | "bind4" | "bind6" | "getpeername4" | "getpeername6" - | "getsockname4" | "getsockname6" | "sendmsg4" | "sendmsg6" | "recvmsg4" - | "recvmsg6" => (), - _ => abort!(attach_type, "invalid attach type"), + if attach_type != "connect4" + && attach_type != "connect6" + && attach_type != "bind4" + && attach_type != "bind6" + && 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 { - item, - attach_type: attach_type.to_string(), - }) + Ok(Self { item, attach_type }) } - pub(crate) fn expand(&self) -> Result { - let section_name: Cow<'_, _> = format!("cgroup/{}", self.attach_type).into(); - let fn_vis = &self.item.vis; - let fn_name = self.item.sig.ident.clone(); - let item = &self.item; - Ok(quote! { + pub(crate) fn expand(&self) -> TokenStream { + let Self { item, attach_type } = self; + let ItemFn { + attrs: _, + vis, + sig, + block: _, + } = item; + let section_name: Cow<'_, _> = format!("cgroup/{attach_type}").into(); + let fn_name = &sig.ident; + quote! { #[no_mangle] #[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)); #item } - }) + } } } @@ -63,7 +74,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "cgroup/connect4"] @@ -89,7 +100,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "cgroup/connect6"] @@ -115,7 +126,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "cgroup/bind4"] @@ -141,7 +152,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "cgroup/bind6"] @@ -167,7 +178,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "cgroup/getpeername4"] @@ -193,7 +204,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "cgroup/getpeername6"] @@ -219,7 +230,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "cgroup/getsockname4"] @@ -245,7 +256,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "cgroup/getsockname6"] @@ -271,7 +282,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "cgroup/sendmsg4"] @@ -297,7 +308,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "cgroup/sendmsg6"] @@ -323,7 +334,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "cgroup/recvmsg4"] @@ -349,7 +360,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "cgroup/recvmsg6"] diff --git a/aya-ebpf-macros/src/cgroup_sockopt.rs b/aya-ebpf-macros/src/cgroup_sockopt.rs index ae4c7752c..7be166467 100644 --- a/aya-ebpf-macros/src/cgroup_sockopt.rs +++ b/aya-ebpf-macros/src/cgroup_sockopt.rs @@ -1,46 +1,50 @@ use std::borrow::Cow; use proc_macro2::TokenStream; -use proc_macro_error::abort; +use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _}; use quote::quote; -use syn::{Ident, ItemFn, Result}; +use syn::{spanned::Spanned as _, Ident, ItemFn}; pub(crate) struct CgroupSockopt { item: ItemFn, - attach_type: String, + attach_type: Ident, } impl CgroupSockopt { - pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { + pub(crate) fn parse( + attrs: TokenStream, + item: TokenStream, + ) -> Result { if attrs.is_empty() { - abort!(attrs, "expected attach type"); + return Err(attrs.span().error("missing attach type")); } let item = syn::parse2(item)?; let attach_type: Ident = syn::parse2(attrs)?; - match attach_type.to_string().as_str() { - "getsockopt" | "setsockopt" => (), - _ => abort!(attach_type, "invalid attach type"), + if attach_type != "getsockopt" && attach_type != "setsockopt" { + return Err(attach_type.span().error("invalid attach type")); } - Ok(CgroupSockopt { - item, - attach_type: attach_type.to_string(), - }) + Ok(Self { item, attach_type }) } - pub(crate) fn expand(&self) -> Result { - let section_name: Cow<'_, _> = format!("cgroup/{}", self.attach_type).into(); - let fn_vis = &self.item.vis; - let fn_name = self.item.sig.ident.clone(); - let item = &self.item; - Ok(quote! { + pub(crate) fn expand(&self) -> TokenStream { + let Self { item, attach_type } = self; + let ItemFn { + attrs: _, + vis, + sig, + block: _, + } = item; + let section_name: Cow<'_, _> = format!("cgroup/{attach_type}").into(); + let fn_name = &sig.ident; + quote! { #[no_mangle] #[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)); #item } - }) + } } } @@ -61,7 +65,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote!( #[no_mangle] #[link_section = "cgroup/getsockopt"] @@ -87,7 +91,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote!( #[no_mangle] #[link_section = "cgroup/setsockopt"] diff --git a/aya-ebpf-macros/src/cgroup_sysctl.rs b/aya-ebpf-macros/src/cgroup_sysctl.rs index 451d3f762..e3039102b 100644 --- a/aya-ebpf-macros/src/cgroup_sysctl.rs +++ b/aya-ebpf-macros/src/cgroup_sysctl.rs @@ -1,34 +1,39 @@ use proc_macro2::TokenStream; -use proc_macro_error::abort; +use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _}; use quote::quote; -use syn::{ItemFn, Result}; +use syn::{spanned::Spanned as _, ItemFn}; pub(crate) struct CgroupSysctl { item: ItemFn, } impl CgroupSysctl { - pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { + pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { if !attrs.is_empty() { - abort!(attrs, "unexpected attribute") + return Err(attrs.span().error("unexpected attribute")); } let item = syn::parse2(item)?; - Ok(CgroupSysctl { item }) + Ok(Self { item }) } - pub(crate) fn expand(&self) -> Result { - let fn_vis = &self.item.vis; - let fn_name = self.item.sig.ident.clone(); - let item = &self.item; - Ok(quote! { + pub(crate) fn expand(&self) -> TokenStream { + let Self { item } = self; + let ItemFn { + attrs: _, + vis, + sig, + block: _, + } = item; + let fn_name = &sig.ident; + quote! { #[no_mangle] #[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)); #item } - }) + } } } @@ -49,7 +54,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "cgroup/sysctl"] diff --git a/aya-ebpf-macros/src/fentry.rs b/aya-ebpf-macros/src/fentry.rs index 0856e23f7..ab4975465 100644 --- a/aya-ebpf-macros/src/fentry.rs +++ b/aya-ebpf-macros/src/fentry.rs @@ -13,39 +13,48 @@ pub(crate) struct FEntry { } impl FEntry { - pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { + pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { let item = syn::parse2(item)?; let mut args = syn::parse2(attrs)?; let function = pop_string_arg(&mut args, "function"); let sleepable = pop_bool_arg(&mut args, "sleepable"); err_on_unknown_args(&args)?; - Ok(FEntry { + Ok(Self { item, function, sleepable, }) } - pub(crate) fn expand(&self) -> Result { - let section_prefix = if self.sleepable { "fentry.s" } else { "fentry" }; - let section_name: Cow<'_, _> = if let Some(function) = &self.function { + pub(crate) fn expand(&self) -> TokenStream { + let Self { + 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() } else { section_prefix.into() }; - let fn_vis = &self.item.vis; - let fn_name = self.item.sig.ident.clone(); - let item = &self.item; - Ok(quote! { + let fn_name = &sig.ident; + quote! { #[no_mangle] #[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)); return 0; #item } - }) + } } } @@ -66,7 +75,7 @@ mod tests { }, ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "fentry"] @@ -95,7 +104,7 @@ mod tests { }, ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "fentry/sys_clone"] @@ -124,7 +133,7 @@ mod tests { }, ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "fentry.s"] diff --git a/aya-ebpf-macros/src/fexit.rs b/aya-ebpf-macros/src/fexit.rs index dd4eb2d56..4bda9aee8 100644 --- a/aya-ebpf-macros/src/fexit.rs +++ b/aya-ebpf-macros/src/fexit.rs @@ -13,39 +13,48 @@ pub(crate) struct FExit { } impl FExit { - pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { + pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { let item = syn::parse2(item)?; let mut args = syn::parse2(attrs)?; let function = pop_string_arg(&mut args, "function"); let sleepable = pop_bool_arg(&mut args, "sleepable"); err_on_unknown_args(&args)?; - Ok(FExit { + Ok(Self { item, function, sleepable, }) } - pub(crate) fn expand(&self) -> Result { - let section_prefix = if self.sleepable { "fexit.s" } else { "fexit" }; - let section_name: Cow<'_, _> = if let Some(function) = &self.function { + pub(crate) fn expand(&self) -> TokenStream { + let Self { + 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() } else { section_prefix.into() }; - let fn_vis = &self.item.vis; - let fn_name = self.item.sig.ident.clone(); - let item = &self.item; - Ok(quote! { + let fn_name = &sig.ident; + quote! { #[no_mangle] #[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)); return 0; #item } - }) + } } } @@ -66,7 +75,7 @@ mod tests { }, ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "fexit"] @@ -95,7 +104,7 @@ mod tests { }, ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "fexit/sys_clone"] @@ -124,7 +133,7 @@ mod tests { }, ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "fexit.s/sys_clone"] diff --git a/aya-ebpf-macros/src/kprobe.rs b/aya-ebpf-macros/src/kprobe.rs index 87eedb269..d24b60d7f 100644 --- a/aya-ebpf-macros/src/kprobe.rs +++ b/aya-ebpf-macros/src/kprobe.rs @@ -1,8 +1,9 @@ use std::borrow::Cow; use proc_macro2::TokenStream; +use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _}; use quote::quote; -use syn::{ItemFn, Result}; +use syn::{spanned::Spanned as _, ItemFn}; use crate::args::{err_on_unknown_args, pop_string_arg}; @@ -31,14 +32,23 @@ pub(crate) struct KProbe { } impl KProbe { - pub(crate) fn parse(kind: KProbeKind, attrs: TokenStream, item: TokenStream) -> Result { + pub(crate) fn parse( + kind: KProbeKind, + attrs: TokenStream, + item: TokenStream, + ) -> Result { let item = syn::parse2(item)?; + let span = attrs.span(); let mut args = syn::parse2(attrs)?; let function = pop_string_arg(&mut args, "function"); - let offset = pop_string_arg(&mut args, "offset").map(|v| v.parse::().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)?; - Ok(KProbe { + Ok(Self { kind, item, function, @@ -46,39 +56,42 @@ impl KProbe { }) } - pub(crate) fn expand(&self) -> Result { - let section_name: Cow<'_, _> = if self.function.is_some() && self.offset.is_some() { - format!( - "{}/{}+{}", - self.kind, - self.function.as_ref().unwrap(), - self.offset.unwrap() - ) - .into() - } else if self.function.is_some() { - format!("{}/{}", self.kind, self.function.as_ref().unwrap()).into() - } else { - format!("{}", self.kind).into() + pub(crate) fn expand(&self) -> TokenStream { + let Self { + kind, + function, + offset, + item, + } = self; + let ItemFn { + attrs: _, + vis, + sig, + block: _, + } = 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") { quote! { ProbeContext } } else { quote! { RetProbeContext } }; - let fn_vis = &self.item.vis; - let fn_name = self.item.sig.ident.clone(); - let item = &self.item; - Ok(quote! { + let fn_name = &sig.ident; + quote! { #[no_mangle] #[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)); return 0; #item } - }) + } } } @@ -101,7 +114,7 @@ mod tests { ) .unwrap(); assert_eq!( - kprobe.expand().unwrap().to_string(), + kprobe.expand().to_string(), quote! { #[no_mangle] #[link_section = "kprobe"] @@ -133,7 +146,7 @@ mod tests { ) .unwrap(); assert_eq!( - kprobe.expand().unwrap().to_string(), + kprobe.expand().to_string(), quote! { #[no_mangle] #[link_section = "kprobe/fib_lookup"] @@ -166,7 +179,7 @@ mod tests { ) .unwrap(); assert_eq!( - kprobe.expand().unwrap().to_string(), + kprobe.expand().to_string(), quote! { #[no_mangle] #[link_section = "kprobe/fib_lookup+10"] @@ -196,7 +209,7 @@ mod tests { ) .unwrap(); assert_eq!( - kprobe.expand().unwrap().to_string(), + kprobe.expand().to_string(), quote! { #[no_mangle] #[link_section = "kretprobe"] diff --git a/aya-ebpf-macros/src/lib.rs b/aya-ebpf-macros/src/lib.rs index 8364b683a..acb6fbd93 100644 --- a/aya-ebpf-macros/src/lib.rs +++ b/aya-ebpf-macros/src/lib.rs @@ -37,7 +37,6 @@ use lsm::Lsm; use map::Map; use perf_event::PerfEvent; use proc_macro::TokenStream; -use proc_macro_error::{abort, proc_macro_error}; use raw_tracepoint::RawTracePoint; use sk_lookup::SkLookup; use sk_msg::SkMsg; @@ -48,83 +47,69 @@ use tc::SchedClassifier; use tracepoint::TracePoint; use uprobe::{UProbe, UProbeKind}; use xdp::Xdp; -#[proc_macro_error] + #[proc_macro_attribute] pub fn map(attrs: TokenStream, item: TokenStream) -> TokenStream { match Map::parse(attrs.into(), item.into()) { - Ok(prog) => prog - .expand() - .unwrap_or_else(|err| abort!(err.span(), "{}", err)) - .into(), - Err(err) => abort!(err.span(), "{}", err), + Ok(prog) => prog.expand(), + Err(err) => err.into_compile_error(), } + .into() } -#[proc_macro_error] #[proc_macro_attribute] pub fn kprobe(attrs: TokenStream, item: TokenStream) -> TokenStream { match KProbe::parse(KProbeKind::KProbe, attrs.into(), item.into()) { - Ok(prog) => prog - .expand() - .unwrap_or_else(|err| abort!(err.span(), "{}", err)) - .into(), - Err(err) => abort!(err.span(), "{}", err), + Ok(prog) => prog.expand(), + Err(err) => err.emit_as_expr_tokens(), } + .into() } -#[proc_macro_error] #[proc_macro_attribute] pub fn kretprobe(attrs: TokenStream, item: TokenStream) -> TokenStream { match KProbe::parse(KProbeKind::KRetProbe, attrs.into(), item.into()) { - Ok(prog) => prog - .expand() - .unwrap_or_else(|err| abort!(err.span(), "{}", err)) - .into(), - Err(err) => abort!(err.span(), "{}", err), + Ok(prog) => prog.expand(), + Err(err) => err.emit_as_expr_tokens(), } + .into() } -#[proc_macro_error] #[proc_macro_attribute] pub fn uprobe(attrs: TokenStream, item: TokenStream) -> TokenStream { match UProbe::parse(UProbeKind::UProbe, attrs.into(), item.into()) { - Ok(prog) => prog - .expand() - .unwrap_or_else(|err| abort!(err.span(), "{}", err)) - .into(), - Err(err) => abort!(err.span(), "{}", err), + Ok(prog) => match prog.expand() { + Ok(tokens) => tokens, + Err(err) => err.emit_as_expr_tokens(), + }, + Err(err) => err.emit_as_expr_tokens(), } + .into() } -#[proc_macro_error] #[proc_macro_attribute] pub fn uretprobe(attrs: TokenStream, item: TokenStream) -> TokenStream { match UProbe::parse(UProbeKind::URetProbe, attrs.into(), item.into()) { - Ok(prog) => prog - .expand() - .unwrap_or_else(|err| abort!(err.span(), "{}", err)) - .into(), - Err(err) => abort!(err.span(), "{}", err), + Ok(prog) => match prog.expand() { + Ok(tokens) => tokens, + Err(err) => err.emit_as_expr_tokens(), + }, + Err(err) => err.emit_as_expr_tokens(), } + .into() } -#[proc_macro_error] #[proc_macro_attribute] pub fn sock_ops(attrs: TokenStream, item: TokenStream) -> TokenStream { match SockOps::parse(attrs.into(), item.into()) { - Ok(prog) => prog - .expand() - .unwrap_or_else(|err| abort!(err.span(), "{}", err)) - .into(), - Err(err) => abort!(err.span(), "{}", err), + Ok(prog) => prog.expand(), + Err(err) => err.emit_as_expr_tokens(), } + .into() } -#[proc_macro_error] #[proc_macro_attribute] pub fn sk_msg(attrs: TokenStream, item: TokenStream) -> TokenStream { match SkMsg::parse(attrs.into(), item.into()) { - Ok(prog) => prog - .expand() - .unwrap_or_else(|err| abort!(err.span(), "{}", err)) - .into(), - Err(err) => abort!(err.span(), "{}", err), + Ok(prog) => prog.expand(), + Err(err) => err.emit_as_expr_tokens(), } + .into() } /// 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 /// } /// ``` -#[proc_macro_error] #[proc_macro_attribute] pub fn xdp(attrs: TokenStream, item: TokenStream) -> TokenStream { match Xdp::parse(attrs.into(), item.into()) { - Ok(prog) => prog - .expand() - .unwrap_or_else(|err| abort!(err.span(), "{}", err)) - .into(), - Err(err) => abort!(err.span(), "{}", err), + Ok(prog) => prog.expand(), + Err(err) => err.emit_as_expr_tokens(), } + .into() } -#[proc_macro_error] #[proc_macro_attribute] pub fn classifier(attrs: TokenStream, item: TokenStream) -> TokenStream { match SchedClassifier::parse(attrs.into(), item.into()) { - Ok(prog) => prog - .expand() - .unwrap_or_else(|err| abort!(err.span(), "{}", err)) - .into(), - Err(err) => abort!(err.span(), "{}", err), + Ok(prog) => prog.expand(), + Err(err) => err.emit_as_expr_tokens(), } + .into() } #[proc_macro_attribute] pub fn cgroup_sysctl(attrs: TokenStream, item: TokenStream) -> TokenStream { match CgroupSysctl::parse(attrs.into(), item.into()) { - Ok(prog) => prog - .expand() - .unwrap_or_else(|err| abort!(err.span(), "{}", err)) - .into(), - Err(err) => abort!(err.span(), "{}", err), + Ok(prog) => prog.expand(), + Err(err) => err.emit_as_expr_tokens(), } + .into() } -#[proc_macro_error] #[proc_macro_attribute] pub fn cgroup_sockopt(attrs: TokenStream, item: TokenStream) -> TokenStream { match CgroupSockopt::parse(attrs.into(), item.into()) { - Ok(prog) => prog - .expand() - .unwrap_or_else(|err| abort!(err.span(), "{}", err)) - .into(), - Err(err) => abort!(err.span(), "{}", err), + Ok(prog) => prog.expand(), + Err(err) => err.emit_as_expr_tokens(), } + .into() } -#[proc_macro_error] #[proc_macro_attribute] pub fn cgroup_skb(attrs: TokenStream, item: TokenStream) -> TokenStream { match CgroupSkb::parse(attrs.into(), item.into()) { - Ok(prog) => prog - .expand() - .unwrap_or_else(|err| abort!(err.span(), "{}", err)) - .into(), - Err(err) => abort!(err.span(), "{}", err), + Ok(prog) => prog.expand(), + Err(err) => err.emit_as_expr_tokens(), } + .into() } /// Marks a function as a [`CgroupSockAddr`] eBPF program. @@ -239,51 +210,39 @@ pub fn cgroup_skb(attrs: TokenStream, item: TokenStream) -> TokenStream { /// Ok(0) /// } /// ``` -#[proc_macro_error] #[proc_macro_attribute] pub fn cgroup_sock_addr(attrs: TokenStream, item: TokenStream) -> TokenStream { match CgroupSockAddr::parse(attrs.into(), item.into()) { - Ok(prog) => prog - .expand() - .unwrap_or_else(|err| abort!(err.span(), "{}", err)) - .into(), - Err(err) => abort!(err.span(), "{}", err), + Ok(prog) => prog.expand(), + Err(err) => err.emit_as_expr_tokens(), } + .into() } -#[proc_macro_error] #[proc_macro_attribute] pub fn cgroup_sock(attrs: TokenStream, item: TokenStream) -> TokenStream { match CgroupSock::parse(attrs.into(), item.into()) { - Ok(prog) => prog - .expand() - .unwrap_or_else(|err| abort!(err.span(), "{}", err)) - .into(), - Err(err) => abort!(err.span(), "{}", err), + Ok(prog) => prog.expand(), + Err(err) => err.emit_as_expr_tokens(), } + .into() } -#[proc_macro_error] #[proc_macro_attribute] pub fn tracepoint(attrs: TokenStream, item: TokenStream) -> TokenStream { match TracePoint::parse(attrs.into(), item.into()) { - Ok(prog) => prog - .expand() - .unwrap_or_else(|err| abort!(err.span(), "{}", err)) - .into(), - Err(err) => abort!(err.span(), "{}", err), + Ok(prog) => prog.expand(), + Err(err) => err.emit_as_expr_tokens(), } + .into() } -#[proc_macro_error] #[proc_macro_attribute] pub fn perf_event(attrs: TokenStream, item: TokenStream) -> TokenStream { match PerfEvent::parse(attrs.into(), item.into()) { - Ok(prog) => prog - .expand() - .unwrap_or_else(|err| abort!(err.span(), "{}", err)) - .into(), - Err(err) => abort!(err.span(), "{}", err), + Ok(prog) => prog.expand(), + Err(err) => err.emit_as_expr_tokens(), } + .into() } /// 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) /// } /// ``` -#[proc_macro_error] #[proc_macro_attribute] pub fn raw_tracepoint(attrs: TokenStream, item: TokenStream) -> TokenStream { match RawTracePoint::parse(attrs.into(), item.into()) { - Ok(prog) => prog - .expand() - .unwrap_or_else(|err| abort!(err.span(), "{}", err)) - .into(), - Err(err) => abort!(err.span(), "{}", err), + Ok(prog) => prog.expand(), + Err(err) => err.into_compile_error(), } + .into() } /// 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) /// } /// ``` -#[proc_macro_error] #[proc_macro_attribute] pub fn lsm(attrs: TokenStream, item: TokenStream) -> TokenStream { match Lsm::parse(attrs.into(), item.into()) { - Ok(prog) => prog - .expand() - .unwrap_or_else(|err| abort!(err.span(), "{}", err)) - .into(), - Err(err) => abort!(err.span(), "{}", err), + Ok(prog) => prog.expand(), + Err(err) => err.into_compile_error(), } + .into() } /// 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 -#[proc_macro_error] #[proc_macro_attribute] pub fn btf_tracepoint(attrs: TokenStream, item: TokenStream) -> TokenStream { match BtfTracePoint::parse(attrs.into(), item.into()) { - Ok(prog) => prog - .expand() - .unwrap_or_else(|err| abort!(err.span(), "{}", err)) - .into(), - Err(err) => abort!(err.span(), "{}", err), + Ok(prog) => prog.expand(), + Err(err) => err.into_compile_error(), } + .into() } /// 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()) ///} /// ``` -#[proc_macro_error] #[proc_macro_attribute] pub fn stream_parser(attrs: TokenStream, item: TokenStream) -> TokenStream { sk_skb(SkSkbKind::StreamParser, attrs, item) @@ -471,7 +420,6 @@ pub fn stream_parser(attrs: TokenStream, item: TokenStream) -> TokenStream { /// Ok(sk_action::SK_PASS) ///} /// ``` -#[proc_macro_error] #[proc_macro_attribute] pub fn stream_verdict(attrs: TokenStream, item: TokenStream) -> TokenStream { 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 { match SkSkb::parse(kind, attrs.into(), item.into()) { - Ok(prog) => prog - .expand() - .unwrap_or_else(|err| abort!(err.span(), "{}", err)) - .into(), - Err(err) => abort!(err.span(), "{}", err), + Ok(prog) => prog.expand(), + Err(err) => err.emit_as_expr_tokens(), } + .into() } /// 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 /// } /// ``` -#[proc_macro_error] #[proc_macro_attribute] pub fn socket_filter(attrs: TokenStream, item: TokenStream) -> TokenStream { match SocketFilter::parse(attrs.into(), item.into()) { - Ok(prog) => prog - .expand() - .unwrap_or_else(|err| abort!(err.span(), "{}", err)) - .into(), - Err(err) => abort!(err.span(), "{}", err), + Ok(prog) => prog.expand(), + Err(err) => err.emit_as_expr_tokens(), } + .into() } /// 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) /// } /// ``` -#[proc_macro_error] #[proc_macro_attribute] pub fn fentry(attrs: TokenStream, item: TokenStream) -> TokenStream { match FEntry::parse(attrs.into(), item.into()) { - Ok(prog) => prog - .expand() - .unwrap_or_else(|err| abort!(err.span(), "{}", err)) - .into(), - Err(err) => abort!(err.span(), "{}", err), + Ok(prog) => prog.expand(), + Err(err) => err.into_compile_error(), } + .into() } /// 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) /// } /// ``` -#[proc_macro_error] #[proc_macro_attribute] pub fn fexit(attrs: TokenStream, item: TokenStream) -> TokenStream { match FExit::parse(attrs.into(), item.into()) { - Ok(prog) => prog - .expand() - .unwrap_or_else(|err| abort!(err.span(), "{}", err)) - .into(), - Err(err) => abort!(err.span(), "{}", err), + Ok(prog) => prog.expand(), + Err(err) => err.into_compile_error(), } + .into() } /// 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 /// } /// ``` -#[proc_macro_error] #[proc_macro_attribute] pub fn sk_lookup(attrs: TokenStream, item: TokenStream) -> TokenStream { match SkLookup::parse(attrs.into(), item.into()) { - Ok(prog) => prog - .expand() - .unwrap_or_else(|err| abort!(err.span(), "{}", err)) - .into(), - Err(err) => abort!(err.span(), "{}", err), + Ok(prog) => prog.expand(), + Err(err) => err.emit_as_expr_tokens(), } + .into() } /// 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; /// } /// ``` -#[proc_macro_error] #[proc_macro_attribute] pub fn cgroup_device(attrs: TokenStream, item: TokenStream) -> TokenStream { match CgroupDevice::parse(attrs.into(), item.into()) { - Ok(prog) => prog - .expand() - .unwrap_or_else(|err| abort!(err.span(), "{}", err)) - .into(), - Err(err) => abort!(err.span(), "{}", err), + Ok(prog) => prog.expand(), + Err(err) => err.emit_as_expr_tokens(), } + .into() } diff --git a/aya-ebpf-macros/src/lsm.rs b/aya-ebpf-macros/src/lsm.rs index f32705dba..2eb53dcd2 100644 --- a/aya-ebpf-macros/src/lsm.rs +++ b/aya-ebpf-macros/src/lsm.rs @@ -13,41 +13,50 @@ pub(crate) struct Lsm { } impl Lsm { - pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { + pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { let item = syn::parse2(item)?; let mut args = syn::parse2(attrs)?; let hook = pop_string_arg(&mut args, "hook"); let sleepable = pop_bool_arg(&mut args, "sleepable"); err_on_unknown_args(&args)?; - Ok(Lsm { + Ok(Self { item, hook, sleepable, }) } - pub(crate) fn expand(&self) -> Result { - let section_prefix = if self.sleepable { "lsm.s" } else { "lsm" }; - let section_name: Cow<'_, _> = if let Some(hook) = &self.hook { + pub(crate) fn expand(&self) -> TokenStream { + let Self { + 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() } else { 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 // policy decision. Therefore we do not simply default to a return value // of 0 as in other program types. - Ok(quote! { + let fn_name = &sig.ident; + quote! { #[no_mangle] #[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)); #item } - }) + } } } @@ -71,7 +80,7 @@ mod tests { }, ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "lsm.s/bprm_committed_creds"] @@ -99,7 +108,7 @@ mod tests { }, ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "lsm/bprm_committed_creds"] diff --git a/aya-ebpf-macros/src/map.rs b/aya-ebpf-macros/src/map.rs index e50f45b90..9c85ab877 100644 --- a/aya-ebpf-macros/src/map.rs +++ b/aya-ebpf-macros/src/map.rs @@ -15,18 +15,18 @@ impl Map { let item: ItemStatic = syn::parse2(item)?; let mut args = syn::parse2(attrs)?; 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 { - let section_name: Cow<'_, _> = "maps".to_string().into(); + pub(crate) fn expand(&self) -> TokenStream { + let section_name: Cow<'_, _> = "maps".into(); let name = &self.name; let item = &self.item; - Ok(quote! { + quote! { #[link_section = #section_name] #[export_name = #name] #item - }) + } } } @@ -45,7 +45,7 @@ mod tests { ), ) .unwrap(); - let expanded = map.expand().unwrap(); + let expanded = map.expand(); let expected = quote!( #[link_section = "maps"] #[export_name = "foo"] @@ -63,7 +63,7 @@ mod tests { ), ) .unwrap(); - let expanded = map.expand().unwrap(); + let expanded = map.expand(); let expected = quote!( #[link_section = "maps"] #[export_name = "BAR"] diff --git a/aya-ebpf-macros/src/perf_event.rs b/aya-ebpf-macros/src/perf_event.rs index eb5821676..6abf511ca 100644 --- a/aya-ebpf-macros/src/perf_event.rs +++ b/aya-ebpf-macros/src/perf_event.rs @@ -1,35 +1,40 @@ use proc_macro2::TokenStream; -use proc_macro_error::abort; +use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _}; use quote::quote; -use syn::{ItemFn, Result}; +use syn::{spanned::Spanned as _, ItemFn}; pub(crate) struct PerfEvent { item: ItemFn, } impl PerfEvent { - pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { + pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { if !attrs.is_empty() { - abort!(attrs, "unexpected attribute") + return Err(attrs.span().error("unexpected attribute")); } let item = syn::parse2(item)?; - Ok(PerfEvent { item }) + Ok(Self { item }) } - pub(crate) fn expand(&self) -> Result { - let fn_vis = &self.item.vis; - let fn_name = self.item.sig.ident.clone(); - let item = &self.item; - Ok(quote! { + pub(crate) fn expand(&self) -> TokenStream { + let Self { item } = self; + let ItemFn { + attrs: _, + vis, + sig, + block: _, + } = item; + let fn_name = &sig.ident; + quote! { #[no_mangle] #[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)); return 0; #item } - }) + } } } @@ -50,7 +55,7 @@ mod tests { ), ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "perf_event"] diff --git a/aya-ebpf-macros/src/raw_tracepoint.rs b/aya-ebpf-macros/src/raw_tracepoint.rs index d2780dce1..8883a60b2 100644 --- a/aya-ebpf-macros/src/raw_tracepoint.rs +++ b/aya-ebpf-macros/src/raw_tracepoint.rs @@ -12,33 +12,38 @@ pub(crate) struct RawTracePoint { } impl RawTracePoint { - pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { + pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { let item = syn::parse2(item)?; let mut args = syn::parse2(attrs)?; let tracepoint = pop_string_arg(&mut args, "tracepoint"); err_on_unknown_args(&args)?; - Ok(RawTracePoint { item, tracepoint }) + Ok(Self { item, tracepoint }) } - pub(crate) fn expand(&self) -> Result { - let section_name: Cow<'_, _> = if let Some(tracepoint) = &self.tracepoint { + pub(crate) fn expand(&self) -> TokenStream { + 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() } else { "raw_tp".into() }; - let fn_vis = &self.item.vis; - let fn_name = self.item.sig.ident.clone(); - let item = &self.item; - Ok(quote! { + let fn_name = &sig.ident; + quote! { #[no_mangle] #[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)); return 0; #item } - }) + } } } @@ -59,7 +64,7 @@ mod tests { }, ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "raw_tp/sys_enter"] diff --git a/aya-ebpf-macros/src/sk_lookup.rs b/aya-ebpf-macros/src/sk_lookup.rs index e32890de8..f45dcefea 100644 --- a/aya-ebpf-macros/src/sk_lookup.rs +++ b/aya-ebpf-macros/src/sk_lookup.rs @@ -1,34 +1,39 @@ use proc_macro2::TokenStream; -use proc_macro_error::abort; +use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _}; use quote::quote; -use syn::{ItemFn, Result}; +use syn::{spanned::Spanned as _, ItemFn}; pub(crate) struct SkLookup { item: ItemFn, } impl SkLookup { - pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { + pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { if !attrs.is_empty() { - abort!(attrs, "unexpected attribute") + return Err(attrs.span().error("unexpected attribute")); } let item = syn::parse2(item)?; - Ok(SkLookup { item }) + Ok(Self { item }) } - pub(crate) fn expand(&self) -> Result { - let fn_name = self.item.sig.ident.clone(); - let fn_vis = &self.item.vis; - let item = &self.item; - Ok(quote! { + pub(crate) fn expand(&self) -> TokenStream { + let Self { item } = self; + let ItemFn { + attrs: _, + vis, + sig, + block: _, + } = item; + let fn_name = &sig.ident; + quote! { #[no_mangle] #[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)); #item } - }) + } } } @@ -49,7 +54,7 @@ mod tests { }, ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "sk_lookup"] diff --git a/aya-ebpf-macros/src/sk_msg.rs b/aya-ebpf-macros/src/sk_msg.rs index 6586f8da3..9d1ba6699 100644 --- a/aya-ebpf-macros/src/sk_msg.rs +++ b/aya-ebpf-macros/src/sk_msg.rs @@ -1,34 +1,39 @@ use proc_macro2::TokenStream; -use proc_macro_error::abort; +use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _}; use quote::quote; -use syn::{ItemFn, Result}; +use syn::{spanned::Spanned as _, ItemFn}; pub(crate) struct SkMsg { item: ItemFn, } impl SkMsg { - pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { + pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { if !attrs.is_empty() { - abort!(attrs, "unexpected attribute") + return Err(attrs.span().error("unexpected attribute")); } let item = syn::parse2(item)?; - Ok(SkMsg { item }) + Ok(Self { item }) } - pub(crate) fn expand(&self) -> Result { - let fn_vis = &self.item.vis; - let fn_name = self.item.sig.ident.clone(); - let item = &self.item; - Ok(quote! { + pub(crate) fn expand(&self) -> TokenStream { + let Self { item } = self; + let ItemFn { + attrs: _, + vis, + sig, + block: _, + } = item; + let fn_name = &sig.ident; + quote! { #[no_mangle] #[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)); #item } - }) + } } } @@ -49,7 +54,7 @@ mod tests { }, ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "sk_msg"] diff --git a/aya-ebpf-macros/src/sk_skb.rs b/aya-ebpf-macros/src/sk_skb.rs index c626602f3..6dbb43df3 100644 --- a/aya-ebpf-macros/src/sk_skb.rs +++ b/aya-ebpf-macros/src/sk_skb.rs @@ -1,9 +1,9 @@ use std::borrow::Cow; use proc_macro2::TokenStream; -use proc_macro_error::abort; +use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _}; use quote::quote; -use syn::{ItemFn, Result}; +use syn::{spanned::Spanned as _, ItemFn}; #[allow(clippy::enum_variant_names)] #[derive(Debug, Copy, Clone)] @@ -28,29 +28,37 @@ pub(crate) struct SkSkb { } impl SkSkb { - pub(crate) fn parse(kind: SkSkbKind, attrs: TokenStream, item: TokenStream) -> Result { + pub(crate) fn parse( + kind: SkSkbKind, + attrs: TokenStream, + item: TokenStream, + ) -> Result { if !attrs.is_empty() { - abort!(attrs, "unexpected attribute"); + return Err(attrs.span().error("unexpected attribute")); } let item = syn::parse2(item)?; - Ok(SkSkb { item, kind }) + Ok(Self { item, kind }) } - pub(crate) fn expand(&self) -> Result { - let kind = &self.kind; + pub(crate) fn expand(&self) -> TokenStream { + let Self { kind, item } = self; + let ItemFn { + attrs: _, + vis, + sig, + block: _, + } = item; let section_name: Cow<'_, _> = format!("sk_skb/{kind}").into(); - let fn_name = self.item.sig.ident.clone(); - let fn_vis = &self.item.vis; - let item = &self.item; - Ok(quote! { + let fn_name = &sig.ident; + quote! { #[no_mangle] #[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)); #item } - }) + } } } @@ -72,7 +80,7 @@ mod tests { }, ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "sk_skb/stream_parser"] @@ -99,7 +107,7 @@ mod tests { }, ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "sk_skb/stream_verdict"] diff --git a/aya-ebpf-macros/src/sock_ops.rs b/aya-ebpf-macros/src/sock_ops.rs index 91b9c5c48..a268746c9 100644 --- a/aya-ebpf-macros/src/sock_ops.rs +++ b/aya-ebpf-macros/src/sock_ops.rs @@ -1,34 +1,39 @@ use proc_macro2::TokenStream; -use proc_macro_error::abort; +use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _}; use quote::quote; -use syn::{ItemFn, Result}; +use syn::{spanned::Spanned as _, ItemFn}; pub(crate) struct SockOps { item: ItemFn, } impl SockOps { - pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { + pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { if !attrs.is_empty() { - abort!(attrs, "unexpected attribute") + return Err(attrs.span().error("unexpected attribute")); } let item = syn::parse2(item)?; - Ok(SockOps { item }) + Ok(Self { item }) } - pub(crate) fn expand(&self) -> Result { - let fn_vis = &self.item.vis; - let fn_name = self.item.sig.ident.clone(); - let item = &self.item; - Ok(quote! { + pub(crate) fn expand(&self) -> TokenStream { + let Self { item } = self; + let ItemFn { + attrs: _, + vis, + sig, + block: _, + } = item; + let fn_name = &sig.ident; + quote! { #[no_mangle] #[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)); #item } - }) + } } } @@ -49,7 +54,7 @@ mod tests { }, ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "sockops"] diff --git a/aya-ebpf-macros/src/socket_filter.rs b/aya-ebpf-macros/src/socket_filter.rs index 27c0b7c77..b45bd993e 100644 --- a/aya-ebpf-macros/src/socket_filter.rs +++ b/aya-ebpf-macros/src/socket_filter.rs @@ -1,34 +1,39 @@ use proc_macro2::TokenStream; -use proc_macro_error::abort; +use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _}; use quote::quote; -use syn::{ItemFn, Result}; +use syn::{spanned::Spanned as _, ItemFn}; pub(crate) struct SocketFilter { item: ItemFn, } impl SocketFilter { - pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { + pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { if !attrs.is_empty() { - abort!(attrs, "unexpected attribute") + return Err(attrs.span().error("unexpected attribute")); } let item = syn::parse2(item)?; - Ok(SocketFilter { item }) + Ok(Self { item }) } - pub(crate) fn expand(&self) -> Result { - let fn_name = self.item.sig.ident.clone(); - let fn_vis = &self.item.vis; - let item = &self.item; - Ok(quote! { + pub(crate) fn expand(&self) -> TokenStream { + let Self { item } = self; + let ItemFn { + attrs: _, + vis, + sig, + block: _, + } = item; + let fn_name = &sig.ident; + quote! { #[no_mangle] #[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)); #item } - }) + } } } @@ -49,7 +54,7 @@ mod tests { }, ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "socket"] diff --git a/aya-ebpf-macros/src/tc.rs b/aya-ebpf-macros/src/tc.rs index 0b816674e..85157f1ae 100644 --- a/aya-ebpf-macros/src/tc.rs +++ b/aya-ebpf-macros/src/tc.rs @@ -1,34 +1,39 @@ use proc_macro2::TokenStream; -use proc_macro_error::abort; +use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _}; use quote::quote; -use syn::{ItemFn, Result}; +use syn::{spanned::Spanned as _, ItemFn}; pub(crate) struct SchedClassifier { item: ItemFn, } impl SchedClassifier { - pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { + pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { if !attrs.is_empty() { - abort!(attrs, "unexpected attribute") + return Err(attrs.span().error("unexpected attribute")); } let item = syn::parse2(item)?; - Ok(SchedClassifier { item }) + Ok(Self { item }) } - pub(crate) fn expand(&self) -> Result { - let fn_vis = &self.item.vis; - let fn_name = self.item.sig.ident.clone(); - let item = &self.item; - Ok(quote! { + pub(crate) fn expand(&self) -> TokenStream { + let Self { item } = self; + let ItemFn { + attrs: _, + vis, + sig, + block: _, + } = item; + let fn_name = &sig.ident; + quote! { #[no_mangle] #[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)); #item } - }) + } } } @@ -49,7 +54,7 @@ mod tests { }, ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "classifier"] diff --git a/aya-ebpf-macros/src/tracepoint.rs b/aya-ebpf-macros/src/tracepoint.rs index 7377346f5..d972766e3 100644 --- a/aya-ebpf-macros/src/tracepoint.rs +++ b/aya-ebpf-macros/src/tracepoint.rs @@ -1,52 +1,64 @@ use std::borrow::Cow; use proc_macro2::TokenStream; -use proc_macro_error::abort; +use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _}; use quote::quote; -use syn::{ItemFn, Result}; +use syn::{spanned::Spanned as _, ItemFn}; use crate::args::{err_on_unknown_args, pop_string_arg}; pub(crate) struct TracePoint { item: ItemFn, - category: Option, - name: Option, + name_and_category: Option<(String, String)>, } impl TracePoint { - pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { + pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { let item = syn::parse2(item)?; + let span = attrs.span(); let mut args = syn::parse2(attrs)?; let name = pop_string_arg(&mut args, "name"); let category = pop_string_arg(&mut args, "category"); err_on_unknown_args(&args)?; - Ok(TracePoint { - item, - category, - name, - }) + match (name, category) { + (None, None) => Ok(Self { + item, + 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 { - let section_name: Cow<'_, _> = match (&self.category, &self.name) { - (Some(category), Some(name)) => format!("tracepoint/{}/{}", category, name).into(), - (Some(_), None) => abort!(self.item, "expected `name` and `category` arguments"), - (None, Some(_)) => abort!(self.item, "expected `name` and `category` arguments"), - _ => "tracepoint".into(), + pub(crate) fn expand(&self) -> TokenStream { + let Self { + item, + name_and_category, + } = self; + 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 fn_name = self.item.sig.ident.clone(); - let item = &self.item; - Ok(quote! { + let ItemFn { + attrs: _, + vis, + sig, + block: _, + } = item; + let fn_name = &sig.ident; + quote! { #[no_mangle] #[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)); return 0; #item } - }) + } } } @@ -67,7 +79,7 @@ mod tests { }, ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "tracepoint/syscalls/sys_enter_bind"] diff --git a/aya-ebpf-macros/src/uprobe.rs b/aya-ebpf-macros/src/uprobe.rs index 5ce012394..2d43766c9 100644 --- a/aya-ebpf-macros/src/uprobe.rs +++ b/aya-ebpf-macros/src/uprobe.rs @@ -1,9 +1,9 @@ use std::borrow::Cow; use proc_macro2::TokenStream; -use proc_macro_error::abort; +use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _}; 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}; @@ -34,15 +34,24 @@ pub(crate) struct UProbe { } impl UProbe { - pub(crate) fn parse(kind: UProbeKind, attrs: TokenStream, item: TokenStream) -> Result { + pub(crate) fn parse( + kind: UProbeKind, + attrs: TokenStream, + item: TokenStream, + ) -> Result { let item = syn::parse2(item)?; + let span = attrs.span(); let mut args = syn::parse2(attrs)?; let path = pop_string_arg(&mut args, "path"); let function = pop_string_arg(&mut args, "function"); - let offset = pop_string_arg(&mut args, "offset").map(|v| v.parse::().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"); err_on_unknown_args(&args)?; - Ok(UProbe { + Ok(Self { kind, item, path, @@ -52,39 +61,38 @@ impl UProbe { }) } - pub(crate) fn expand(&self) -> Result { - let prefix = if self.sleepable { - format!("{}.s", self.kind) - } else { - format!("{}", self.kind) - }; - let section_name: Cow<'_, _> = if self.path.is_some() && self.offset.is_some() { - if self.function.is_none() { - abort!(self.item.sig.ident, "expected `function` attribute"); - } - let mut path = self.path.as_ref().unwrap().clone(); - if path.starts_with('/') { - path.remove(0); - } - format!( - "{}/{}:{}+{}", - prefix, - path, - self.function.as_ref().unwrap(), - self.offset.unwrap() - ) - .into() - } else if self.path.is_some() { - if self.function.is_none() { - abort!(self.item.sig.ident, "expected `function` attribute"); - } - let mut path = self.path.as_ref().unwrap().clone(); - if path.starts_with('/') { - path.remove(0); + pub(crate) fn expand(&self) -> Result { + let Self { + kind, + path, + function, + offset, + item, + sleepable, + } = self; + let ItemFn { + attrs: _, + vis, + sig, + block: _, + } = item; + let mut prefix = kind.to_string(); + if *sleepable { + prefix.push_str(".s"); + } + let section_name: Cow<'_, _> = match path { + None => prefix.into(), + Some(path) => { + let path = path.strip_prefix("/").unwrap_or(path); + // TODO: check this in parse instead. + let function = function + .as_deref() + .ok_or(item.sig.span().error("expected `function` attribute"))?; + match offset { + 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") { @@ -92,13 +100,11 @@ impl UProbe { } else { quote! { RetProbeContext } }; - let fn_vis = &self.item.vis; - let fn_name = self.item.sig.ident.clone(); - let item = &self.item; + let fn_name = &sig.ident; Ok(quote! { #[no_mangle] #[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)); return 0; diff --git a/aya-ebpf-macros/src/xdp.rs b/aya-ebpf-macros/src/xdp.rs index 3944fb19f..dde8b906f 100644 --- a/aya-ebpf-macros/src/xdp.rs +++ b/aya-ebpf-macros/src/xdp.rs @@ -1,6 +1,7 @@ use proc_macro2::TokenStream; +use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _}; 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}; @@ -17,8 +18,9 @@ pub(crate) enum XdpMap { } impl Xdp { - pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { + pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { let item = syn::parse2(item)?; + let span = attrs.span(); let mut args: Args = syn::parse2(attrs)?; let frags = pop_bool_arg(&mut args, "frags"); @@ -26,39 +28,42 @@ impl Xdp { Some("cpumap") => Some(XdpMap::CpuMap), Some("devmap") => Some(XdpMap::DevMap), Some(name) => { - return Err(Error::new_spanned( - "map", - format!("Invalid value. Expected 'cpumap' or 'devmap', found '{name}'"), - )) + return Err(span.error(format!( + "Invalid value. Expected 'cpumap' or 'devmap', found '{name}'" + ))) } None => None, }; err_on_unknown_args(&args)?; - Ok(Xdp { item, frags, map }) + Ok(Self { item, frags, map }) } - pub(crate) fn expand(&self) -> Result { - let mut section_name = vec![if self.frags { "xdp.frags" } else { "xdp" }]; - match self.map { + pub(crate) fn expand(&self) -> TokenStream { + let Self { item, frags, map } = self; + 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::DevMap) => section_name.push("devmap"), None => (), }; let section_name = section_name.join("/"); - - let fn_vis = &self.item.vis; - let fn_name = self.item.sig.ident.clone(); - let item = &self.item; - Ok(quote! { + let fn_name = &sig.ident; + quote! { #[no_mangle] #[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)); #item } - }) + } } } @@ -79,7 +84,7 @@ mod tests { }, ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "xdp"] @@ -105,7 +110,7 @@ mod tests { }, ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "xdp.frags"] @@ -131,7 +136,7 @@ mod tests { }, ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "xdp/cpumap"] @@ -157,7 +162,7 @@ mod tests { }, ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "xdp/devmap"] @@ -197,7 +202,7 @@ mod tests { }, ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "xdp.frags/cpumap"] @@ -223,7 +228,7 @@ mod tests { }, ) .unwrap(); - let expanded = prog.expand().unwrap(); + let expanded = prog.expand(); let expected = quote! { #[no_mangle] #[link_section = "xdp.frags/devmap"]