xref: /linux/drivers/android/binder/trace.rs (revision c16ce856e422e73a54c41131e0332de1afe09b8b)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 // Copyright (C) 2025 Google LLC.
4 
5 use crate::transaction::Transaction;
6 
7 use core::ptr;
8 
9 use kernel::bindings::{rust_binder_transaction, task_struct};
10 use kernel::error::Result;
11 use kernel::ffi::{c_int, c_uint, c_ulong};
12 use kernel::task::Task;
13 use kernel::tracepoint::declare_trace;
14 
15 declare_trace! {
16     unsafe fn binder_ioctl(cmd: c_uint, arg: c_ulong);
17     unsafe fn binder_ioctl_done(ret: c_int);
18     unsafe fn binder_read_done(ret: c_int);
19     unsafe fn binder_write_done(ret: c_int);
20     unsafe fn binder_wait_for_work(proc_work: bool, transaction_stack: bool, thread_todo: bool);
21     unsafe fn binder_transaction(reply: bool, t: rust_binder_transaction, thread: *mut task_struct);
22     unsafe fn binder_transaction_received(t: rust_binder_transaction);
23     unsafe fn binder_transaction_fd_send(t_debug_id: c_int, fd: c_int, offset: usize);
24     unsafe fn binder_transaction_fd_recv(t_debug_id: c_int, fd: c_int, offset: usize);
25     unsafe fn binder_command(cmd: u32);
26     unsafe fn binder_return(ret: u32);
27 }
28 
29 #[inline]
30 fn raw_transaction(t: &Transaction) -> rust_binder_transaction {
31     ptr::from_ref(t).cast_mut().cast()
32 }
33 
34 #[inline]
35 fn to_errno(ret: Result) -> i32 {
36     match ret {
37         Ok(()) => 0,
38         Err(err) => err.to_errno(),
39     }
40 }
41 
42 #[inline]
43 pub(crate) fn trace_ioctl(cmd: u32, arg: usize) {
44     // SAFETY: Always safe to call.
45     unsafe { binder_ioctl(cmd, arg as c_ulong) }
46 }
47 
48 #[inline]
49 pub(crate) fn trace_ioctl_done(ret: Result) {
50     // SAFETY: Always safe to call.
51     unsafe { binder_ioctl_done(to_errno(ret)) }
52 }
53 #[inline]
54 pub(crate) fn trace_read_done(ret: Result) {
55     // SAFETY: Always safe to call.
56     unsafe { binder_read_done(to_errno(ret)) }
57 }
58 #[inline]
59 pub(crate) fn trace_write_done(ret: Result) {
60     // SAFETY: Always safe to call.
61     unsafe { binder_write_done(to_errno(ret)) }
62 }
63 
64 #[inline]
65 pub(crate) fn trace_wait_for_work(proc_work: bool, transaction_stack: bool, thread_todo: bool) {
66     // SAFETY: Always safe to call.
67     unsafe { binder_wait_for_work(proc_work, transaction_stack, thread_todo) }
68 }
69 
70 #[inline]
71 pub(crate) fn trace_transaction(reply: bool, t: &Transaction, thread: Option<&Task>) {
72     let thread = match thread {
73         Some(thread) => thread.as_ptr(),
74         None => core::ptr::null_mut(),
75     };
76     // SAFETY: The raw transaction is valid for the duration of this call. The thread pointer is
77     // valid or null.
78     unsafe { binder_transaction(reply, raw_transaction(t), thread) }
79 }
80 
81 #[inline]
82 pub(crate) fn trace_transaction_received(t: &Transaction) {
83     // SAFETY: The raw transaction is valid for the duration of this call.
84     unsafe { binder_transaction_received(raw_transaction(t)) }
85 }
86 
87 #[inline]
88 pub(crate) fn trace_transaction_fd_send(t_debug_id: usize, fd: u32, offset: usize) {
89     // SAFETY: This function is always safe to call.
90     unsafe { binder_transaction_fd_send(t_debug_id as c_int, fd as c_int, offset) }
91 }
92 #[inline]
93 pub(crate) fn trace_transaction_fd_recv(t_debug_id: usize, fd: u32, offset: usize) {
94     // SAFETY: This function is always safe to call.
95     unsafe { binder_transaction_fd_recv(t_debug_id as c_int, fd as c_int, offset) }
96 }
97 
98 #[inline]
99 pub(crate) fn trace_command(cmd: u32) {
100     // SAFETY: This function is always safe to call.
101     unsafe { binder_command(cmd) }
102 }
103 #[inline]
104 pub(crate) fn trace_return(ret: u32) {
105     // SAFETY: This function is always safe to call.
106     unsafe { binder_return(ret) }
107 }
108