Browse Source

feat(log): add support for logging raw pointer types

* Requires the usage of `:p` display hint.
* Will, like stdlib, log with `0x` prefix.
Christian A. Jacobsen 2 weeks ago
parent
commit
a98b638fa9

+ 22 - 0
aya-log-common/src/lib.rs

@@ -97,6 +97,10 @@ impl LowerMacFormatter for [u8; 6] {}
 pub trait UpperMacFormatter {}
 impl UpperMacFormatter for [u8; 6] {}
 
+pub trait PointerFormatter {}
+impl<T> PointerFormatter for *const T {}
+impl<T> PointerFormatter for *mut T {}
+
 #[repr(u8)]
 #[derive(Copy, Clone, Debug, IntoPrimitive)]
 pub enum RecordFieldKind {
@@ -144,6 +148,8 @@ pub enum ArgumentKind {
 
     Bytes,
     Str,
+
+    Pointer,
 }
 
 /// All display hints
@@ -162,6 +168,8 @@ pub enum DisplayHint {
     LowerMac,
     /// `:MAC`
     UpperMac,
+    /// `:p`
+    Pointer,
 }
 
 mod sealed {
@@ -282,6 +290,20 @@ impl Argument for DisplayHint {
     }
 }
 
+impl<T> sealed::Sealed for *const T {}
+impl<T> Argument for *const T {
+    fn as_argument(&self) -> (ArgumentKind, impl AsRef<[u8]>) {
+        (ArgumentKind::Pointer, (*self as usize).to_ne_bytes())
+    }
+}
+
+impl<T> sealed::Sealed for *mut T {}
+impl<T> Argument for *mut T {
+    fn as_argument(&self) -> (ArgumentKind, impl AsRef<[u8]>) {
+        (ArgumentKind::Pointer, (*self as usize).to_ne_bytes())
+    }
+}
+
 fn wire_len(value: &[u8]) -> Option<[u8; 2]> {
     match LogValueLength::try_from(value.len()) {
         Ok(wire_len) => Some(wire_len.to_ne_bytes()),

+ 3 - 0
aya-log-ebpf-macros/src/expand.rs

@@ -127,6 +127,9 @@ pub(crate) fn log(args: LogArgs, level_expr: Option<TokenStream>) -> Result<Toke
                     DisplayHint::UpperMac => {
                         (quote!(DisplayHint::UpperMac), quote!(UpperMacFormatter))
                     }
+                    DisplayHint::Pointer => {
+                        (quote!(DisplayHint::Pointer), quote!(PointerFormatter))
+                    }
                 };
                 let hint = quote!(::aya_log_ebpf::macro_support::#hint);
                 let arg = quote!(

+ 3 - 2
aya-log-parser/src/lib.rs

@@ -59,11 +59,12 @@ fn parse_param(input: &str) -> Result<Parameter, String> {
     let hint = match input.strip_prefix(":") {
         Some(input) => match input {
             "" => return Err("malformed format string (missing display hint after ':')".into()),
-            "p" | "x" => DisplayHint::LowerHex,
+            "x" => DisplayHint::LowerHex,
             "X" => DisplayHint::UpperHex,
             "i" => DisplayHint::Ip,
             "mac" => DisplayHint::LowerMac,
             "MAC" => DisplayHint::UpperMac,
+            "p" => DisplayHint::Pointer,
             input => return Err(format!("unknown display hint: {input:?}")),
         },
         None => {
@@ -155,7 +156,7 @@ mod test {
                 }),
                 Fragment::Literal(" lmao {} {something} ".into()),
                 Fragment::Parameter(Parameter {
-                    hint: DisplayHint::LowerHex
+                    hint: DisplayHint::Pointer
                 }),
             ])
         );

+ 47 - 0
aya-log/src/lib.rs

@@ -284,6 +284,19 @@ impl Formatter<[u8; 6]> for UpperMacFormatter {
     }
 }
 
+pub struct PointerFormatter;
+impl<T> Formatter<*const T> for PointerFormatter {
+    fn format(v: *const T) -> String {
+        format!("{v:p}")
+    }
+}
+
+impl<T> Formatter<*mut T> for PointerFormatter {
+    fn format(v: *mut T) -> String {
+        format!("{v:p}")
+    }
+}
+
 trait Format {
     fn format(&self, last_hint: Option<DisplayHintWrapper>) -> Result<String, ()>;
 }
@@ -307,6 +320,7 @@ impl Format for u32 {
             Some(DisplayHint::Ip) => Ok(Ipv4Formatter::format(*self)),
             Some(DisplayHint::LowerMac) => Err(()),
             Some(DisplayHint::UpperMac) => Err(()),
+            Some(DisplayHint::Pointer) => Err(()),
             None => Ok(DefaultFormatter::format(self)),
         }
     }
@@ -321,6 +335,7 @@ impl Format for Ipv4Addr {
             Some(DisplayHint::Ip) => Ok(Ipv4Formatter::format(*self)),
             Some(DisplayHint::LowerMac) => Err(()),
             Some(DisplayHint::UpperMac) => Err(()),
+            Some(DisplayHint::Pointer) => Err(()),
             None => Ok(Ipv4Formatter::format(*self)),
         }
     }
@@ -335,6 +350,7 @@ impl Format for Ipv6Addr {
             Some(DisplayHint::Ip) => Ok(Ipv6Formatter::format(*self)),
             Some(DisplayHint::LowerMac) => Err(()),
             Some(DisplayHint::UpperMac) => Err(()),
+            Some(DisplayHint::Pointer) => Err(()),
             None => Ok(Ipv6Formatter::format(*self)),
         }
     }
@@ -349,6 +365,7 @@ impl Format for [u8; 4] {
             Some(DisplayHint::Ip) => Ok(Ipv4Formatter::format(*self)),
             Some(DisplayHint::LowerMac) => Err(()),
             Some(DisplayHint::UpperMac) => Err(()),
+            Some(DisplayHint::Pointer) => Err(()),
             None => Ok(Ipv4Formatter::format(*self)),
         }
     }
@@ -363,6 +380,7 @@ impl Format for [u8; 6] {
             Some(DisplayHint::Ip) => Err(()),
             Some(DisplayHint::LowerMac) => Ok(LowerMacFormatter::format(*self)),
             Some(DisplayHint::UpperMac) => Ok(UpperMacFormatter::format(*self)),
+            Some(DisplayHint::Pointer) => Err(()),
             None => Err(()),
         }
     }
@@ -377,6 +395,7 @@ impl Format for [u8; 16] {
             Some(DisplayHint::Ip) => Ok(Ipv6Formatter::format(*self)),
             Some(DisplayHint::LowerMac) => Err(()),
             Some(DisplayHint::UpperMac) => Err(()),
+            Some(DisplayHint::Pointer) => Err(()),
             None => Err(()),
         }
     }
@@ -391,6 +410,7 @@ impl Format for [u16; 8] {
             Some(DisplayHint::Ip) => Ok(Ipv6Formatter::format(*self)),
             Some(DisplayHint::LowerMac) => Err(()),
             Some(DisplayHint::UpperMac) => Err(()),
+            Some(DisplayHint::Pointer) => Err(()),
             None => Err(()),
         }
     }
@@ -407,6 +427,7 @@ macro_rules! impl_format {
                     Some(DisplayHint::Ip) => Err(()),
                     Some(DisplayHint::LowerMac) => Err(()),
                     Some(DisplayHint::UpperMac) => Err(()),
+                    Some(DisplayHint::Pointer) => Err(()),
                     None => Ok(DefaultFormatter::format(self)),
                 }
             }
@@ -436,6 +457,7 @@ macro_rules! impl_format_float {
                     Some(DisplayHint::Ip) => Err(()),
                     Some(DisplayHint::LowerMac) => Err(()),
                     Some(DisplayHint::UpperMac) => Err(()),
+                    Some(DisplayHint::Pointer) => Err(()),
                     None => Ok(DefaultFormatter::format(self)),
                 }
             }
@@ -446,6 +468,24 @@ macro_rules! impl_format_float {
 impl_format_float!(f32);
 impl_format_float!(f64);
 
+impl<T> Format for *const T {
+    fn format(&self, last_hint: Option<DisplayHintWrapper>) -> Result<String, ()> {
+        match last_hint.map(|DisplayHintWrapper(dh)| dh) {
+            Some(DisplayHint::Pointer) => Ok(PointerFormatter::format(*self)),
+            _ => Err(()),
+        }
+    }
+}
+
+impl<T> Format for *mut T {
+    fn format(&self, last_hint: Option<DisplayHintWrapper>) -> Result<String, ()> {
+        match last_hint.map(|DisplayHintWrapper(dh)| dh) {
+            Some(DisplayHint::Pointer) => Ok(PointerFormatter::format(*self)),
+            _ => Err(()),
+        }
+    }
+}
+
 #[derive(Error, Debug)]
 pub enum Error {
     #[error("{} not found", MAP_NAME)]
@@ -732,6 +772,13 @@ fn log_buf<T: ?Sized + Log>(mut buf: &[u8], logger: &T) -> Result<(), ()> {
                 }
                 Err(e) => error!("received invalid utf8 string: {e}"),
             },
+            ArgumentKind::Pointer => {
+                let value = value
+                    .try_into()
+                    .map_err(|std::array::TryFromSliceError { .. }| ())?;
+                let ptr = usize::from_ne_bytes(value) as *const ();
+                full_log_msg.push_str(&ptr.format(last_hint.take())?);
+            }
         }
 
         buf = rest;

+ 2 - 1
ebpf/aya-log-ebpf/src/lib.rs

@@ -14,7 +14,8 @@ pub mod macro_support {
     use aya_ebpf::maps::RingBuf;
     pub use aya_log_common::{
         Argument, DefaultFormatter, DisplayHint, Field, Header, IpFormatter, Level, LogValueLength,
-        LowerHexFormatter, LowerMacFormatter, UpperHexFormatter, UpperMacFormatter,
+        LowerHexFormatter, LowerMacFormatter, PointerFormatter, UpperHexFormatter,
+        UpperMacFormatter,
     };
 
     // This cfg_attr prevents compilation failures on macOS where the generated section name doesn't

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

@@ -89,6 +89,8 @@ fn test_log(ctx: ProbeContext) {
         &ctx,
         "{} {} {} {} {} {} {}", header, tmp, kind, value, size, op, buf
     );
+    let ptr = 0xdeadbeef as *const u8;
+    debug!(&ctx, "ptr: {:p}", ptr);
 
     // Testing compilation only.
     if false {

+ 9 - 0
test/integration-test/src/tests/log.rs

@@ -187,6 +187,15 @@ fn log() {
         })
     );
 
+    assert_eq!(
+        records.next(),
+        Some(&CapturedLog {
+            body: "ptr: 0xdeadbeef".into(),
+            level: Level::Debug,
+            target: "log".into(),
+        })
+    );
+
     assert_eq!(
         records.next(),
         Some(&CapturedLog {

+ 9 - 0
xtask/public-api/aya-log-common.txt

@@ -15,6 +15,7 @@ pub aya_log_common::ArgumentKind::I8
 pub aya_log_common::ArgumentKind::Ipv4Addr
 pub aya_log_common::ArgumentKind::Ipv6Addr
 pub aya_log_common::ArgumentKind::Isize
+pub aya_log_common::ArgumentKind::Pointer
 pub aya_log_common::ArgumentKind::Str
 pub aya_log_common::ArgumentKind::U16
 pub aya_log_common::ArgumentKind::U32
@@ -57,6 +58,7 @@ pub aya_log_common::DisplayHint::Default = 1
 pub aya_log_common::DisplayHint::Ip
 pub aya_log_common::DisplayHint::LowerHex
 pub aya_log_common::DisplayHint::LowerMac
+pub aya_log_common::DisplayHint::Pointer
 pub aya_log_common::DisplayHint::UpperHex
 pub aya_log_common::DisplayHint::UpperMac
 impl aya_log_common::Argument for aya_log_common::DisplayHint
@@ -215,6 +217,10 @@ impl aya_log_common::Argument for u8
 pub fn u8::as_argument(&self) -> (aya_log_common::ArgumentKind, impl core::convert::AsRef<[u8]>)
 impl aya_log_common::Argument for usize
 pub fn usize::as_argument(&self) -> (aya_log_common::ArgumentKind, impl core::convert::AsRef<[u8]>)
+impl<T> aya_log_common::Argument for *const T
+pub fn *const T::as_argument(&self) -> (aya_log_common::ArgumentKind, impl core::convert::AsRef<[u8]>)
+impl<T> aya_log_common::Argument for *mut T
+pub fn *mut T::as_argument(&self) -> (aya_log_common::ArgumentKind, impl core::convert::AsRef<[u8]>)
 impl<const N: usize> aya_log_common::Argument for [u8; N]
 pub fn [u8; N]::as_argument(&self) -> (aya_log_common::ArgumentKind, impl core::convert::AsRef<[u8]>)
 pub trait aya_log_common::DefaultFormatter
@@ -260,6 +266,9 @@ impl aya_log_common::LowerHexFormatter for usize
 impl<const N: usize> aya_log_common::LowerHexFormatter for &[u8; N]
 pub trait aya_log_common::LowerMacFormatter
 impl aya_log_common::LowerMacFormatter for [u8; 6]
+pub trait aya_log_common::PointerFormatter
+impl<T> aya_log_common::PointerFormatter for *const T
+impl<T> aya_log_common::PointerFormatter for *mut T
 pub trait aya_log_common::UpperHexFormatter
 impl aya_log_common::UpperHexFormatter for &[u8]
 impl aya_log_common::UpperHexFormatter for i16

+ 31 - 0
xtask/public-api/aya-log.txt

@@ -223,6 +223,33 @@ impl<T> core::borrow::BorrowMut<T> for aya_log::LowerMacFormatter where T: ?core
 pub fn aya_log::LowerMacFormatter::borrow_mut(&mut self) -> &mut T
 impl<T> core::convert::From<T> for aya_log::LowerMacFormatter
 pub fn aya_log::LowerMacFormatter::from(t: T) -> T
+pub struct aya_log::PointerFormatter
+impl<T> aya_log::Formatter<*const T> for aya_log::PointerFormatter
+pub fn aya_log::PointerFormatter::format(v: *const T) -> alloc::string::String
+impl<T> aya_log::Formatter<*mut T> for aya_log::PointerFormatter
+pub fn aya_log::PointerFormatter::format(v: *mut T) -> alloc::string::String
+impl core::marker::Freeze for aya_log::PointerFormatter
+impl core::marker::Send for aya_log::PointerFormatter
+impl core::marker::Sync for aya_log::PointerFormatter
+impl core::marker::Unpin for aya_log::PointerFormatter
+impl core::panic::unwind_safe::RefUnwindSafe for aya_log::PointerFormatter
+impl core::panic::unwind_safe::UnwindSafe for aya_log::PointerFormatter
+impl<T, U> core::convert::Into<U> for aya_log::PointerFormatter where U: core::convert::From<T>
+pub fn aya_log::PointerFormatter::into(self) -> U
+impl<T, U> core::convert::TryFrom<U> for aya_log::PointerFormatter where U: core::convert::Into<T>
+pub type aya_log::PointerFormatter::Error = core::convert::Infallible
+pub fn aya_log::PointerFormatter::try_from(value: U) -> core::result::Result<T, <T as core::convert::TryFrom<U>>::Error>
+impl<T, U> core::convert::TryInto<U> for aya_log::PointerFormatter where U: core::convert::TryFrom<T>
+pub type aya_log::PointerFormatter::Error = <U as core::convert::TryFrom<T>>::Error
+pub fn aya_log::PointerFormatter::try_into(self) -> core::result::Result<U, <U as core::convert::TryFrom<T>>::Error>
+impl<T> core::any::Any for aya_log::PointerFormatter where T: 'static + ?core::marker::Sized
+pub fn aya_log::PointerFormatter::type_id(&self) -> core::any::TypeId
+impl<T> core::borrow::Borrow<T> for aya_log::PointerFormatter where T: ?core::marker::Sized
+pub fn aya_log::PointerFormatter::borrow(&self) -> &T
+impl<T> core::borrow::BorrowMut<T> for aya_log::PointerFormatter where T: ?core::marker::Sized
+pub fn aya_log::PointerFormatter::borrow_mut(&mut self) -> &mut T
+impl<T> core::convert::From<T> for aya_log::PointerFormatter
+pub fn aya_log::PointerFormatter::from(t: T) -> T
 pub struct aya_log::UpperHexBytesFormatter
 impl aya_log::Formatter<&[u8]> for aya_log::UpperHexBytesFormatter
 pub fn aya_log::UpperHexBytesFormatter::format(v: &[u8]) -> alloc::string::String
@@ -309,6 +336,10 @@ impl aya_log::Formatter<[u8; 6]> for aya_log::LowerMacFormatter
 pub fn aya_log::LowerMacFormatter::format(v: [u8; 6]) -> alloc::string::String
 impl aya_log::Formatter<[u8; 6]> for aya_log::UpperMacFormatter
 pub fn aya_log::UpperMacFormatter::format(v: [u8; 6]) -> alloc::string::String
+impl<T> aya_log::Formatter<*const T> for aya_log::PointerFormatter
+pub fn aya_log::PointerFormatter::format(v: *const T) -> alloc::string::String
+impl<T> aya_log::Formatter<*mut T> for aya_log::PointerFormatter
+pub fn aya_log::PointerFormatter::format(v: *mut T) -> alloc::string::String
 impl<T> aya_log::Formatter<T> for aya_log::DefaultFormatter where T: alloc::string::ToString
 pub fn aya_log::DefaultFormatter::format(v: T) -> alloc::string::String
 impl<T> aya_log::Formatter<T> for aya_log::Ipv4Formatter where T: core::convert::Into<core::net::ip_addr::Ipv4Addr>