fentry.rs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  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<FEntry> {
  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(FEntry {
  19. item,
  20. function,
  21. sleepable,
  22. })
  23. }
  24. pub(crate) fn expand(&self) -> Result<TokenStream> {
  25. let section_prefix = if self.sleepable { "fentry.s" } else { "fentry" };
  26. let section_name: Cow<'_, _> = if let Some(function) = &self.function {
  27. format!("{}/{}", section_prefix, function).into()
  28. } else {
  29. section_prefix.into()
  30. };
  31. let fn_vis = &self.item.vis;
  32. let fn_name = self.item.sig.ident.clone();
  33. let item = &self.item;
  34. Ok(quote! {
  35. #[no_mangle]
  36. #[link_section = #section_name]
  37. #fn_vis fn #fn_name(ctx: *mut ::core::ffi::c_void) -> i32 {
  38. let _ = #fn_name(::aya_bpf::programs::FEntryContext::new(ctx));
  39. return 0;
  40. #item
  41. }
  42. })
  43. }
  44. }
  45. #[cfg(test)]
  46. mod tests {
  47. use syn::parse_quote;
  48. use super::*;
  49. #[test]
  50. fn test_fentry() {
  51. let prog = FEntry::parse(
  52. parse_quote! {},
  53. parse_quote! {
  54. fn sys_clone(ctx: &mut aya_bpf::programs::FEntryContext) -> i32 {
  55. 0
  56. }
  57. },
  58. )
  59. .unwrap();
  60. let expanded = prog.expand().unwrap();
  61. let expected = quote! {
  62. #[no_mangle]
  63. #[link_section = "fentry"]
  64. fn sys_clone(ctx: *mut ::core::ffi::c_void) -> i32 {
  65. let _ = sys_clone(::aya_bpf::programs::FEntryContext::new(ctx));
  66. return 0;
  67. fn sys_clone(ctx: &mut aya_bpf::programs::FEntryContext) -> i32 {
  68. 0
  69. }
  70. }
  71. };
  72. assert_eq!(expected.to_string(), expanded.to_string());
  73. }
  74. #[test]
  75. fn test_fentry_with_function() {
  76. let prog = FEntry::parse(
  77. parse_quote! {
  78. function = "sys_clone"
  79. },
  80. parse_quote! {
  81. fn sys_clone(ctx: &mut aya_bpf::programs::FEntryContext) -> i32 {
  82. 0
  83. }
  84. },
  85. )
  86. .unwrap();
  87. let expanded = prog.expand().unwrap();
  88. let expected = quote! {
  89. #[no_mangle]
  90. #[link_section = "fentry/sys_clone"]
  91. fn sys_clone(ctx: *mut ::core::ffi::c_void) -> i32 {
  92. let _ = sys_clone(::aya_bpf::programs::FEntryContext::new(ctx));
  93. return 0;
  94. fn sys_clone(ctx: &mut aya_bpf::programs::FEntryContext) -> i32 {
  95. 0
  96. }
  97. }
  98. };
  99. assert_eq!(expected.to_string(), expanded.to_string());
  100. }
  101. #[test]
  102. fn test_fentry_sleepable() {
  103. let prog = FEntry::parse(
  104. parse_quote! {
  105. sleepable
  106. },
  107. parse_quote! {
  108. fn sys_clone(ctx: &mut aya_bpf::programs::FEntryContext) -> i32 {
  109. 0
  110. }
  111. },
  112. )
  113. .unwrap();
  114. let expanded = prog.expand().unwrap();
  115. let expected = quote! {
  116. #[no_mangle]
  117. #[link_section = "fentry.s"]
  118. fn sys_clone(ctx: *mut ::core::ffi::c_void) -> i32 {
  119. let _ = sys_clone(::aya_bpf::programs::FEntryContext::new(ctx));
  120. return 0;
  121. fn sys_clone(ctx: &mut aya_bpf::programs::FEntryContext) -> i32 {
  122. 0
  123. }
  124. }
  125. };
  126. assert_eq!(expected.to_string(), expanded.to_string());
  127. }
  128. }