fentry.rs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. use std::borrow::Cow;
  2. use proc_macro2::TokenStream;
  3. use quote::quote;
  4. use syn::{ItemFn, Result};
  5. use crate::args::{err_on_unknown_args, pop_bool_arg, pop_string_arg};
  6. pub(crate) struct FEntry {
  7. item: ItemFn,
  8. function: Option<String>,
  9. sleepable: bool,
  10. }
  11. impl FEntry {
  12. pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result<Self> {
  13. let item = syn::parse2(item)?;
  14. let mut args = syn::parse2(attrs)?;
  15. let function = pop_string_arg(&mut args, "function");
  16. let sleepable = pop_bool_arg(&mut args, "sleepable");
  17. err_on_unknown_args(&args)?;
  18. Ok(Self {
  19. item,
  20. function,
  21. sleepable,
  22. })
  23. }
  24. pub(crate) fn expand(&self) -> TokenStream {
  25. let Self {
  26. item,
  27. function,
  28. sleepable,
  29. } = self;
  30. let ItemFn {
  31. attrs: _,
  32. vis,
  33. sig,
  34. block: _,
  35. } = item;
  36. let section_prefix = if *sleepable { "fentry.s" } else { "fentry" };
  37. let section_name: Cow<'_, _> = if let Some(function) = function {
  38. format!("{}/{}", section_prefix, function).into()
  39. } else {
  40. section_prefix.into()
  41. };
  42. let fn_name = &sig.ident;
  43. quote! {
  44. #[unsafe(no_mangle)]
  45. #[unsafe(link_section = #section_name)]
  46. #vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> i32 {
  47. let _ = #fn_name(::aya_ebpf::programs::FEntryContext::new(ctx));
  48. return 0;
  49. #item
  50. }
  51. }
  52. }
  53. }
  54. #[cfg(test)]
  55. mod tests {
  56. use syn::parse_quote;
  57. use super::*;
  58. #[test]
  59. fn test_fentry() {
  60. let prog = FEntry::parse(
  61. parse_quote! {},
  62. parse_quote! {
  63. fn sys_clone(ctx: &mut aya_ebpf::programs::FEntryContext) -> i32 {
  64. 0
  65. }
  66. },
  67. )
  68. .unwrap();
  69. let expanded = prog.expand();
  70. let expected = quote! {
  71. #[unsafe(no_mangle)]
  72. #[unsafe(link_section = "fentry")]
  73. fn sys_clone(ctx: *mut ::core::ffi::c_void) -> i32 {
  74. let _ = sys_clone(::aya_ebpf::programs::FEntryContext::new(ctx));
  75. return 0;
  76. fn sys_clone(ctx: &mut aya_ebpf::programs::FEntryContext) -> i32 {
  77. 0
  78. }
  79. }
  80. };
  81. assert_eq!(expected.to_string(), expanded.to_string());
  82. }
  83. #[test]
  84. fn test_fentry_with_function() {
  85. let prog = FEntry::parse(
  86. parse_quote! {
  87. function = "sys_clone"
  88. },
  89. parse_quote! {
  90. fn sys_clone(ctx: &mut aya_ebpf::programs::FEntryContext) -> i32 {
  91. 0
  92. }
  93. },
  94. )
  95. .unwrap();
  96. let expanded = prog.expand();
  97. let expected = quote! {
  98. #[unsafe(no_mangle)]
  99. #[unsafe(link_section = "fentry/sys_clone")]
  100. fn sys_clone(ctx: *mut ::core::ffi::c_void) -> i32 {
  101. let _ = sys_clone(::aya_ebpf::programs::FEntryContext::new(ctx));
  102. return 0;
  103. fn sys_clone(ctx: &mut aya_ebpf::programs::FEntryContext) -> i32 {
  104. 0
  105. }
  106. }
  107. };
  108. assert_eq!(expected.to_string(), expanded.to_string());
  109. }
  110. #[test]
  111. fn test_fentry_sleepable() {
  112. let prog = FEntry::parse(
  113. parse_quote! {
  114. sleepable
  115. },
  116. parse_quote! {
  117. fn sys_clone(ctx: &mut aya_ebpf::programs::FEntryContext) -> i32 {
  118. 0
  119. }
  120. },
  121. )
  122. .unwrap();
  123. let expanded = prog.expand();
  124. let expected = quote! {
  125. #[unsafe(no_mangle)]
  126. #[unsafe(link_section = "fentry.s")]
  127. fn sys_clone(ctx: *mut ::core::ffi::c_void) -> i32 {
  128. let _ = sys_clone(::aya_ebpf::programs::FEntryContext::new(ctx));
  129. return 0;
  130. fn sys_clone(ctx: &mut aya_ebpf::programs::FEntryContext) -> i32 {
  131. 0
  132. }
  133. }
  134. };
  135. assert_eq!(expected.to_string(), expanded.to_string());
  136. }
  137. }