Browse Source

aya-log-ebpf: avoid requiring Copy

Before this change:
```
error[E0382]: use of moved value: `no_copy`
  --> test/integration-ebpf/src/log.rs:35:9
   |
33 |         let no_copy = NoCopy {};
   |             ------- move occurs because `no_copy` has type `NoCopy`, which does not implement the `Copy` trait
34 |
35 |         debug!(&ctx, "{:x}", no_copy.consume());
   |         ^^^^^^^^^^^^^^^^^^^^^-------^---------^
   |         |                    |       |
   |         |                    |       `no_copy` moved due to this method call
   |         |                    use occurs due to use in closure
   |         value used here after move
   |
note: `NoCopy::consume` takes ownership of the receiver `self`, which moves `no_copy`
  --> test/integration-ebpf/src/log.rs:28:24
   |
28 |             fn consume(self) -> u64 {
   |                        ^^^^
   = note: this error originates in the macro `debug` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0382`.
error: could not compile `integration-ebpf` (bin "log") due to previous error
```
Tamir Duberstein 1 year ago
parent
commit
de7972483b
3 changed files with 43 additions and 20 deletions
  1. 18 6
      aya-log-common/src/lib.rs
  2. 10 14
      aya-log-ebpf-macros/src/expand.rs
  3. 15 0
      test/integration-ebpf/src/log.rs

+ 18 - 6
aya-log-common/src/lib.rs

@@ -86,17 +86,29 @@ pub trait UpperMacFormatter {}
 impl UpperMacFormatter for [u8; 6] {}
 
 #[inline(always)]
-pub fn check_impl_default<T: DefaultFormatter>(_v: T) {}
+pub fn check_impl_default<T: DefaultFormatter>(t: T) -> T {
+    t
+}
 #[inline(always)]
-pub fn check_impl_lower_hex<T: LowerHexFormatter>(_v: T) {}
+pub fn check_impl_lower_hex<T: LowerHexFormatter>(t: T) -> T {
+    t
+}
 #[inline(always)]
-pub fn check_impl_upper_hex<T: UpperHexFormatter>(_v: T) {}
+pub fn check_impl_upper_hex<T: UpperHexFormatter>(t: T) -> T {
+    t
+}
 #[inline(always)]
-pub fn check_impl_ip<T: IpFormatter>(_v: T) {}
+pub fn check_impl_ip<T: IpFormatter>(t: T) -> T {
+    t
+}
 #[inline(always)]
-pub fn check_impl_lower_mac<T: LowerMacFormatter>(_v: T) {}
+pub fn check_impl_lower_mac<T: LowerMacFormatter>(t: T) -> T {
+    t
+}
 #[inline(always)]
-pub fn check_impl_upper_mac<T: UpperMacFormatter>(_v: T) {}
+pub fn check_impl_upper_mac<T: UpperMacFormatter>(t: T) -> T {
+    t
+}
 
 #[repr(u8)]
 #[derive(Copy, Clone, Debug)]

+ 10 - 14
aya-log-ebpf-macros/src/expand.rs

@@ -4,7 +4,7 @@ use syn::{
     parse::{Parse, ParseStream},
     parse_str,
     punctuated::Punctuated,
-    Error, Expr, LitStr, Result, Token,
+    Error, Expr, ExprCall, LitStr, Result, Token,
 };
 
 use aya_log_common::DisplayHint;
@@ -125,8 +125,6 @@ pub(crate) fn log(args: LogArgs, level: Option<TokenStream>) -> Result<TokenStre
     let mut arg_i = 0;
 
     let mut values = Vec::new();
-    let mut f_keys = Vec::new();
-    let mut f_values = Vec::new();
     for fragment in fragments {
         match fragment {
             Fragment::Literal(s) => {
@@ -137,11 +135,16 @@ pub(crate) fn log(args: LogArgs, level: Option<TokenStream>) -> Result<TokenStre
                     Some(ref args) => args[arg_i].clone(),
                     None => return Err(Error::new(format_string.span(), "no arguments provided")),
                 };
-                values.push(hint_to_expr(p.hint)?);
-                values.push(arg.clone());
+                let hint = hint_to_expr(p.hint)?;
+                let format_check = hint_to_format_check(p.hint)?;
+                values.push(hint);
+                values.push(Expr::Call(ExprCall {
+                    attrs: Vec::new(),
+                    func: Box::new(format_check),
+                    paren_token: Default::default(),
+                    args: Punctuated::from_iter(std::iter::once(arg)),
+                }));
 
-                f_keys.push(hint_to_format_check(p.hint)?);
-                f_values.push(arg.clone());
                 arg_i += 1;
             }
         }
@@ -150,15 +153,8 @@ pub(crate) fn log(args: LogArgs, level: Option<TokenStream>) -> Result<TokenStre
     let num_args = values.len();
     let values_iter = values.iter();
 
-    let f_keys = f_keys.iter();
-    let f_values = f_values.iter();
-
     Ok(quote! {
         {
-            #(
-                #f_keys(#f_values);
-            )*
-
             if let Some(buf_ptr) = unsafe { ::aya_log_ebpf::AYA_LOG_BUF.get_ptr_mut(0) } {
                 let buf = unsafe { &mut *buf_ptr };
                 if let Ok(header_len) = ::aya_log_ebpf::write_record_header(

+ 15 - 0
test/integration-ebpf/src/log.rs

@@ -19,6 +19,21 @@ pub fn test_log(ctx: ProbeContext) {
     warn!(&ctx, "hex lc: {:x}, hex uc: {:X}", hex, hex);
     let hex = [0xde, 0xad, 0xbe, 0xef].as_slice();
     debug!(&ctx, "hex lc: {:x}, hex uc: {:X}", hex, hex);
+
+    // Testing compilation only.
+    if false {
+        struct NoCopy {}
+
+        impl NoCopy {
+            fn consume(self) -> u64 {
+                0xdeadbeef
+            }
+        }
+
+        let no_copy = NoCopy {};
+
+        debug!(&ctx, "{:x}", no_copy.consume());
+    }
 }
 
 #[panic_handler]