perf_event.rs 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. use proc_macro2::TokenStream;
  2. use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _};
  3. use quote::quote;
  4. use syn::{spanned::Spanned as _, ItemFn};
  5. pub(crate) struct PerfEvent {
  6. item: ItemFn,
  7. }
  8. impl PerfEvent {
  9. pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self, Diagnostic> {
  10. if !attrs.is_empty() {
  11. return Err(attrs.span().error("unexpected attribute"));
  12. }
  13. let item = syn::parse2(item)?;
  14. Ok(Self { item })
  15. }
  16. pub(crate) fn expand(&self) -> TokenStream {
  17. let Self { item } = self;
  18. let ItemFn {
  19. attrs: _,
  20. vis,
  21. sig,
  22. block: _,
  23. } = item;
  24. let fn_name = &sig.ident;
  25. quote! {
  26. #[no_mangle]
  27. #[link_section = "perf_event"]
  28. #vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> u32 {
  29. let _ = #fn_name(::aya_ebpf::programs::PerfEventContext::new(ctx));
  30. return 0;
  31. #item
  32. }
  33. }
  34. }
  35. }
  36. #[cfg(test)]
  37. mod tests {
  38. use syn::parse_quote;
  39. use super::*;
  40. #[test]
  41. fn test_perf_event() {
  42. let prog = PerfEvent::parse(
  43. parse_quote!(),
  44. parse_quote!(
  45. fn foo(ctx: PerfEventContext) -> i32 {
  46. 0
  47. }
  48. ),
  49. )
  50. .unwrap();
  51. let expanded = prog.expand();
  52. let expected = quote! {
  53. #[no_mangle]
  54. #[link_section = "perf_event"]
  55. fn foo(ctx: *mut ::core::ffi::c_void) -> u32 {
  56. let _ = foo(::aya_ebpf::programs::PerfEventContext::new(ctx));
  57. return 0;
  58. fn foo(ctx: PerfEventContext) -> i32 {
  59. 0
  60. }
  61. }
  62. };
  63. assert_eq!(expected.to_string(), expanded.to_string());
  64. }
  65. }