Skip to main content

jtrace_bindings/
jtrace_types.rs

1// Copyright 2026 The Fuchsia Authors
2//
3// Use of this source code is governed by a MIT-style
4// license that can be found in the LICENSE file or at
5// https://opensource.org/licenses/MIT
6
7//! Rust bindings and field/entry helper types for jump trace (`jtrace`).
8
9#![no_std]
10
11use core::ffi::CStr;
12use core::mem::size_of;
13use core::ptr::NonNull;
14
15use fbl::{HasRefCount, Recyclable, RefPtr};
16use kalloc::Box;
17
18#[expect(non_camel_case_types)]
19mod sys {
20    include!(rustenv_path::envpath!("JTRACE_BINDINGS_RS"));
21}
22
23pub use sys::{
24    jtrace_IsPersistent as IsPersistent, jtrace_LargeEntry as LargeEntry,
25    jtrace_SmallEntry as SmallEntry, jtrace_TraceBufferType as TraceBufferType,
26    jtrace_UseLargeEntries as UseLargeEntries, jtrace_UseMonoTimestamps as UseMonoTimestamps,
27    jtrace_internal_FileFuncLineInfo as FileFuncLineInfo,
28};
29
30// All arguments provided to trace entries are either 32 or 64 bits, and will be
31// rendered as just hex when the trace needs to be dumped. Define a few helper
32// structs which will allow users to pass _any_ data type to a trace entry,
33// provided that it will fit in the storage.
34
35/// Helper converting up to 32-bit non-float values into a `u32` trace field
36/// (`jtrace::internal::Field32`).
37#[repr(transparent)]
38#[derive(Debug, Clone, Copy, PartialEq, Eq)]
39pub struct Field32 {
40    /// Stored 32-bit field value.
41    pub val: u32,
42}
43
44impl Field32 {
45    /// Creates a `Field32` from a `u32`.
46    #[inline]
47    pub const fn new(val: u32) -> Self {
48        Self { val }
49    }
50}
51
52// Macro used to implement `From<T>` for primitive integer types up to 32 bits because Rust
53// coherence rules forbid a blanket `impl<T> From<T> for Field32` (which conflicts with
54// reflexive `impl<T> From<T> for T`).
55macro_rules! impl_from_for_field32 {
56    ($($t:ty),* $(,)?) => {
57        $(
58            impl From<$t> for Field32 {
59                #[inline]
60                fn from(v: $t) -> Self {
61                    const { assert!(size_of::<$t>() <= 4) };
62                    Self { val: v as u32 }
63                }
64            }
65        )*
66    };
67}
68
69impl_from_for_field32!(u8, u16, u32, i8, i16, i32, char);
70
71/// Helper converting up to 64-bit non-float values and pointers into a `u64` trace field
72/// (`jtrace::internal::Field64`).
73#[repr(transparent)]
74#[derive(Debug, Clone, Copy, PartialEq, Eq)]
75pub struct Field64 {
76    /// Stored 64-bit field value.
77    pub val: u64,
78}
79
80impl Field64 {
81    /// Creates a `Field64` from a `u64`.
82    #[inline]
83    pub const fn new(val: u64) -> Self {
84        Self { val }
85    }
86}
87
88// Macro used to implement `From<T>` for primitive integer types up to 64 bits because Rust
89// coherence rules forbid a blanket `impl<T> From<T> for Field64` (which conflicts with
90// reflexive `impl<T> From<T> for T`).
91macro_rules! impl_from_for_field64 {
92    ($($t:ty),* $(,)?) => {
93        $(
94            impl From<$t> for Field64 {
95                #[inline]
96                fn from(v: $t) -> Self {
97                    const { assert!(size_of::<$t>() <= 8) };
98                    Self { val: v as u64 }
99                }
100            }
101        )*
102    };
103}
104
105impl_from_for_field64!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, char);
106
107impl<T> From<*const T> for Field64 {
108    #[inline]
109    fn from(ptr: *const T) -> Self {
110        Self { val: ptr.addr() as u64 }
111    }
112}
113
114impl<T> From<*mut T> for Field64 {
115    #[inline]
116    fn from(ptr: *mut T) -> Self {
117        Self { val: ptr.addr() as u64 }
118    }
119}
120
121impl<T> From<NonNull<T>> for Field64 {
122    #[inline]
123    fn from(ptr: NonNull<T>) -> Self {
124        Self { val: ptr.addr().get() as u64 }
125    }
126}
127
128impl<T> From<&Box<T>> for Field64 {
129    #[inline]
130    fn from(b: &Box<T>) -> Self {
131        Self { val: Box::as_ptr(b).addr() as u64 }
132    }
133}
134
135impl<T: HasRefCount + Recyclable> From<&RefPtr<T>> for Field64 {
136    #[inline]
137    fn from(r: &RefPtr<T>) -> Self {
138        Self { val: RefPtr::as_ptr(r).addr() as u64 }
139    }
140}
141
142impl FileFuncLineInfo {
143    /// Creates a new `FileFuncLineInfo` from static C string literals and a line number.
144    #[inline]
145    pub const fn new(file: &'static CStr, func: &'static CStr, line: i32) -> Self {
146        Self { file: file.as_ptr(), func: func.as_ptr(), line, __bindgen_padding_0: [0; 4] }
147    }
148}
149
150// SAFETY: `FileFuncLineInfo` has no interior mutability, and its `file` and `func` pointers
151// only ever point to immutable `'static` C string literals.
152unsafe impl Sync for FileFuncLineInfo {}
153
154impl Default for SmallEntry {
155    #[inline]
156    fn default() -> Self {
157        Self { ts_ticks: 0, tag: core::ptr::null(), cpu_id: 0, a: 0 }
158    }
159}
160
161impl SmallEntry {
162    /// Creates a new `SmallEntry` matching C++
163    /// `Entry<UseLargeEntries::No>(tag, ffl_info, a)`.
164    #[inline]
165    pub fn new(
166        tag: &'static CStr,
167        _ffl_info: &'static FileFuncLineInfo,
168        a: impl Into<Field32>,
169    ) -> Self {
170        Self { ts_ticks: 0, tag: tag.as_ptr(), cpu_id: 0, a: a.into().val }
171    }
172}
173
174impl Default for LargeEntry {
175    #[inline]
176    fn default() -> Self {
177        Self {
178            ts_ticks: 0,
179            tag: core::ptr::null(),
180            ffl_info: core::ptr::null(),
181            tid: 0,
182            e: 0,
183            f: 0,
184            a: 0,
185            b: 0,
186            c: 0,
187            d: 0,
188            cpu_id: 0,
189            padding: 0,
190        }
191    }
192}
193
194impl LargeEntry {
195    /// Creates a new `LargeEntry` matching C++
196    /// `Entry<UseLargeEntries::Yes>(tag, ffl_info, a, b, c, d, e, f)`.
197    #[inline]
198    #[allow(clippy::too_many_arguments)]
199    pub fn new(
200        tag: &'static CStr,
201        ffl_info: &'static FileFuncLineInfo,
202        a: impl Into<Field32>,
203        b: impl Into<Field32>,
204        c: impl Into<Field32>,
205        d: impl Into<Field32>,
206        e: impl Into<Field64>,
207        f: impl Into<Field64>,
208    ) -> Self {
209        Self {
210            ts_ticks: 0,
211            tag: tag.as_ptr(),
212            ffl_info,
213            tid: 0,
214            e: e.into().val,
215            f: f.into().val,
216            a: a.into().val,
217            b: b.into().val,
218            c: c.into().val,
219            d: d.into().val,
220            cpu_id: 0,
221            padding: 0,
222        }
223    }
224}