diff --git a/aya-log-common/src/lib.rs b/aya-log-common/src/lib.rs index 37591f7e..449c891b 100644 --- a/aya-log-common/src/lib.rs +++ b/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 PointerFormatter for *const T {} +impl 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 sealed::Sealed for *const T {} +impl Argument for *const T { + fn as_argument(&self) -> (ArgumentKind, impl AsRef<[u8]>) { + (ArgumentKind::Pointer, (*self as usize).to_ne_bytes()) + } +} + +impl sealed::Sealed for *mut T {} +impl 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()), diff --git a/aya-log-ebpf-macros/src/expand.rs b/aya-log-ebpf-macros/src/expand.rs index ab8dfc9e..24345092 100644 --- a/aya-log-ebpf-macros/src/expand.rs +++ b/aya-log-ebpf-macros/src/expand.rs @@ -127,6 +127,9 @@ pub(crate) fn log(args: LogArgs, level_expr: Option) -> Result { (quote!(DisplayHint::UpperMac), quote!(UpperMacFormatter)) } + DisplayHint::Pointer => { + (quote!(DisplayHint::Pointer), quote!(PointerFormatter)) + } }; let hint = quote!(::aya_log_ebpf::macro_support::#hint); let arg = quote!( diff --git a/aya-log-parser/src/lib.rs b/aya-log-parser/src/lib.rs index d01a17ed..8f3e9eb9 100644 --- a/aya-log-parser/src/lib.rs +++ b/aya-log-parser/src/lib.rs @@ -59,11 +59,12 @@ fn parse_param(input: &str) -> Result { 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 }), ]) ); diff --git a/aya-log/src/lib.rs b/aya-log/src/lib.rs index 04bb79b1..9c7c6492 100644 --- a/aya-log/src/lib.rs +++ b/aya-log/src/lib.rs @@ -284,6 +284,19 @@ impl Formatter<[u8; 6]> for UpperMacFormatter { } } +pub struct PointerFormatter; +impl Formatter<*const T> for PointerFormatter { + fn format(v: *const T) -> String { + format!("{v:p}") + } +} + +impl Formatter<*mut T> for PointerFormatter { + fn format(v: *mut T) -> String { + format!("{v:p}") + } +} + trait Format { fn format(&self, last_hint: Option) -> Result; } @@ -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 Format for *const T { + fn format(&self, last_hint: Option) -> Result { + match last_hint.map(|DisplayHintWrapper(dh)| dh) { + Some(DisplayHint::Pointer) => Ok(PointerFormatter::format(*self)), + _ => Err(()), + } + } +} + +impl Format for *mut T { + fn format(&self, last_hint: Option) -> Result { + 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(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; diff --git a/ebpf/aya-log-ebpf/src/lib.rs b/ebpf/aya-log-ebpf/src/lib.rs index 7238c006..6be37975 100644 --- a/ebpf/aya-log-ebpf/src/lib.rs +++ b/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 diff --git a/test/integration-ebpf/src/log.rs b/test/integration-ebpf/src/log.rs index 2abb5566..3e7bf5b8 100644 --- a/test/integration-ebpf/src/log.rs +++ b/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 { diff --git a/test/integration-test/src/tests/log.rs b/test/integration-test/src/tests/log.rs index e1659d54..1973bf84 100644 --- a/test/integration-test/src/tests/log.rs +++ b/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 { diff --git a/xtask/public-api/aya-log-common.txt b/xtask/public-api/aya-log-common.txt index 481b273e..7187da8e 100644 --- a/xtask/public-api/aya-log-common.txt +++ b/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 aya_log_common::Argument for *const T +pub fn *const T::as_argument(&self) -> (aya_log_common::ArgumentKind, impl core::convert::AsRef<[u8]>) +impl aya_log_common::Argument for *mut T +pub fn *mut T::as_argument(&self) -> (aya_log_common::ArgumentKind, impl core::convert::AsRef<[u8]>) impl 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 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 aya_log_common::PointerFormatter for *const T +impl 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 diff --git a/xtask/public-api/aya-log.txt b/xtask/public-api/aya-log.txt index 3583315e..a469879c 100644 --- a/xtask/public-api/aya-log.txt +++ b/xtask/public-api/aya-log.txt @@ -223,6 +223,33 @@ impl core::borrow::BorrowMut for aya_log::LowerMacFormatter where T: ?core pub fn aya_log::LowerMacFormatter::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya_log::LowerMacFormatter pub fn aya_log::LowerMacFormatter::from(t: T) -> T +pub struct aya_log::PointerFormatter +impl aya_log::Formatter<*const T> for aya_log::PointerFormatter +pub fn aya_log::PointerFormatter::format(v: *const T) -> alloc::string::String +impl 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 core::convert::Into for aya_log::PointerFormatter where U: core::convert::From +pub fn aya_log::PointerFormatter::into(self) -> U +impl core::convert::TryFrom for aya_log::PointerFormatter where U: core::convert::Into +pub type aya_log::PointerFormatter::Error = core::convert::Infallible +pub fn aya_log::PointerFormatter::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_log::PointerFormatter where U: core::convert::TryFrom +pub type aya_log::PointerFormatter::Error = >::Error +pub fn aya_log::PointerFormatter::try_into(self) -> core::result::Result>::Error> +impl 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 core::borrow::Borrow for aya_log::PointerFormatter where T: ?core::marker::Sized +pub fn aya_log::PointerFormatter::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_log::PointerFormatter where T: ?core::marker::Sized +pub fn aya_log::PointerFormatter::borrow_mut(&mut self) -> &mut T +impl core::convert::From 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 aya_log::Formatter<*const T> for aya_log::PointerFormatter +pub fn aya_log::PointerFormatter::format(v: *const T) -> alloc::string::String +impl aya_log::Formatter<*mut T> for aya_log::PointerFormatter +pub fn aya_log::PointerFormatter::format(v: *mut T) -> alloc::string::String impl aya_log::Formatter for aya_log::DefaultFormatter where T: alloc::string::ToString pub fn aya_log::DefaultFormatter::format(v: T) -> alloc::string::String impl aya_log::Formatter for aya_log::Ipv4Formatter where T: core::convert::Into