ANDROID: rust_binder: add back tracepoints

Tracepoints were removed from the the vendor module version of Rust
Binder as it required either fixing b/394605825 or hard-coding the
tracepoint declarations as created by bindgen.

As we are moving Rust Binder back into common/, this no longer depends
on invoking bindgen from the DDK. Thus, revert these changes.

Bug: 394605825
Bug: 388786466
Change-Id: I81fe5b2b4c92826c6478606cd78c8fccd8a5c7e4
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
This commit is contained in:
Alice Ryhl
2025-03-13 09:19:56 +00:00
committed by Matthew Maurer
parent dac7c66bc9
commit bf40001347
13 changed files with 776 additions and 28 deletions

View File

@@ -175,6 +175,14 @@ struct NodeInner {
refs: List<NodeRefInfo, { NodeRefInfo::LIST_NODE }>,
}
use core::mem::offset_of;
use kernel::bindings::rb_node_layout;
pub(crate) const NODE_LAYOUT: rb_node_layout = rb_node_layout {
arc_offset: Arc::<Node>::DATA_OFFSET + offset_of!(DTRWrap<Node>, wrapped),
debug_id: offset_of!(Node, debug_id),
ptr: offset_of!(Node, ptr),
};
#[pin_data]
pub(crate) struct Node {
pub(crate) debug_id: usize,

View File

@@ -383,6 +383,13 @@ impl ProcessNodeRefs {
}
}
use core::mem::offset_of;
use kernel::bindings::rb_process_layout;
pub(crate) const PROCESS_LAYOUT: rb_process_layout = rb_process_layout {
arc_offset: Arc::<Process>::DATA_OFFSET,
task: offset_of!(Process, task),
};
/// A process using binder.
///
/// Strictly speaking, there can be multiple of these per process. There is one for each binder fd

View File

@@ -0,0 +1,142 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_RUST_BINDER_H
#define _LINUX_RUST_BINDER_H
#include <uapi/linux/android/binder.h>
#include <uapi/linux/android/binderfs.h>
/*
* These symbols are exposed by `rust_binderfs.c` and exist here so that Rust
* Binder can call them.
*/
int init_rust_binderfs(void);
struct dentry;
struct inode;
struct dentry *rust_binderfs_create_proc_file(struct inode *nodp, int pid);
void rust_binderfs_remove_file(struct dentry *dentry);
typedef void *rust_binder_context;
/**
* struct binder_device - information about a binder device node
* @minor: the minor number used by this device
* @ctx: the Rust Context used by this device, or null for binder-control
*
* This is used as the private data for files directly in binderfs, but not
* files in the binder_logs subdirectory. This struct owns a refcount on `ctx`
* and the entry for `minor` in `binderfs_minors`. For binder-control `ctx` is
* null.
*/
struct binder_device {
int minor;
rust_binder_context ctx;
};
/*
* The internal data types in the Rust Binder driver are opaque to C, so we use
* void pointer typedefs for these types.
*/
typedef void *rust_binder_transaction;
typedef void *rust_binder_thread;
typedef void *rust_binder_process;
typedef void *rust_binder_node;
typedef void *rust_binder_ref_data;
struct rb_transaction_layout {
size_t debug_id;
size_t code;
size_t flags;
size_t from_thread;
size_t to_proc;
size_t target_node;
};
struct rb_thread_layout {
size_t arc_offset;
size_t process;
size_t id;
};
struct rb_process_layout {
size_t arc_offset;
size_t task;
};
struct rb_node_layout {
size_t arc_offset;
size_t debug_id;
size_t ptr;
};
struct rust_binder_layout {
struct rb_transaction_layout t;
struct rb_thread_layout th;
struct rb_process_layout p;
struct rb_node_layout n;
};
extern const struct rust_binder_layout RUST_BINDER_LAYOUT;
static inline size_t rust_binder_transaction_debug_id(rust_binder_transaction t)
{
return * (size_t *) (t + RUST_BINDER_LAYOUT.t.debug_id);
}
static inline u32 rust_binder_transaction_code(rust_binder_transaction t)
{
return * (u32 *) (t + RUST_BINDER_LAYOUT.t.code);
}
static inline u32 rust_binder_transaction_flags(rust_binder_transaction t)
{
return * (u32 *) (t + RUST_BINDER_LAYOUT.t.flags);
}
// Nullable!
static inline rust_binder_node rust_binder_transaction_target_node(rust_binder_transaction t)
{
void *p = * (void **) (t + RUST_BINDER_LAYOUT.t.target_node);
if (p)
p = p + RUST_BINDER_LAYOUT.n.arc_offset;
return p;
}
static inline rust_binder_thread rust_binder_transaction_from_thread(rust_binder_transaction t)
{
void *p = * (void **) (t + RUST_BINDER_LAYOUT.t.from_thread);
return p + RUST_BINDER_LAYOUT.th.arc_offset;
}
static inline rust_binder_process rust_binder_transaction_to_proc(rust_binder_transaction t)
{
void *p = * (void **) (t + RUST_BINDER_LAYOUT.t.to_proc);
return p + RUST_BINDER_LAYOUT.p.arc_offset;
}
static inline rust_binder_process rust_binder_thread_proc(rust_binder_thread t)
{
void *p = * (void **) (t + RUST_BINDER_LAYOUT.th.process);
return p + RUST_BINDER_LAYOUT.p.arc_offset;
}
static inline s32 rust_binder_thread_id(rust_binder_thread t)
{
return * (s32 *) (t + RUST_BINDER_LAYOUT.th.id);
}
static inline struct task_struct *rust_binder_process_task(rust_binder_process t)
{
return * (struct task_struct **) (t + RUST_BINDER_LAYOUT.p.task);
}
static inline size_t rust_binder_node_debug_id(rust_binder_node t)
{
return * (size_t *) (t + RUST_BINDER_LAYOUT.n.debug_id);
}
static inline binder_uintptr_t rust_binder_node_ptr(rust_binder_node t)
{
return * (binder_uintptr_t *) (t + RUST_BINDER_LAYOUT.n.ptr);
}
#endif

View File

@@ -83,6 +83,15 @@ module! {
license: "GPL",
}
use kernel::bindings::rust_binder_layout;
#[no_mangle]
static RUST_BINDER_LAYOUT: rust_binder_layout = rust_binder_layout {
t: transaction::TRANSACTION_LAYOUT,
th: thread::THREAD_LAYOUT,
p: process::PROCESS_LAYOUT,
n: node::NODE_LAYOUT,
};
fn next_debug_id() -> usize {
static NEXT_DEBUG_ID: AtomicUsize = AtomicUsize::new(0);

View File

@@ -6,6 +6,8 @@
* Copyright 2024 Google LLC
*/
#include "rust_binder.h"
const char * const binder_command_strings[] = {
"BC_TRANSACTION",
"BC_REPLY",
@@ -51,3 +53,7 @@ const char * const binder_return_strings[] = {
"BR_ONEWAY_SPAM_SUSPECT",
"BR_TRANSACTION_PENDING_FROZEN"
};
#define CREATE_TRACE_POINTS
#define CREATE_RUST_TRACE_POINTS
#include "rust_binder_events.h"

View File

@@ -0,0 +1,387 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2024 Google, Inc.
*/
#undef TRACE_SYSTEM
#undef TRACE_INCLUDE_FILE
#undef TRACE_INCLUDE_PATH
#define TRACE_SYSTEM rust_binder
#define TRACE_INCLUDE_FILE rust_binder_events
#define TRACE_INCLUDE_PATH ../drivers/android/binder
#if !defined(_RUST_BINDER_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
#define _RUST_BINDER_TRACE_H
#include <linux/tracepoint.h>
TRACE_EVENT(rust_binder_ioctl,
TP_PROTO(unsigned int cmd, unsigned long arg),
TP_ARGS(cmd, arg),
TP_STRUCT__entry(
__field(unsigned int, cmd)
__field(unsigned long, arg)
),
TP_fast_assign(
__entry->cmd = cmd;
__entry->arg = arg;
),
TP_printk("cmd=0x%x arg=0x%lx", __entry->cmd, __entry->arg)
);
DECLARE_EVENT_CLASS(rust_binder_function_return_class,
TP_PROTO(int ret),
TP_ARGS(ret),
TP_STRUCT__entry(
__field(int, ret)
),
TP_fast_assign(
__entry->ret = ret;
),
TP_printk("ret=%d", __entry->ret)
);
#define DEFINE_RBINDER_FUNCTION_RETURN_EVENT(name) \
DEFINE_EVENT(rust_binder_function_return_class, name, \
TP_PROTO(int ret), \
TP_ARGS(ret))
DEFINE_RBINDER_FUNCTION_RETURN_EVENT(rust_binder_ioctl_done);
DEFINE_RBINDER_FUNCTION_RETURN_EVENT(rust_binder_read_done);
DEFINE_RBINDER_FUNCTION_RETURN_EVENT(rust_binder_write_done);
TRACE_EVENT(rust_binder_set_priority,
TP_PROTO(struct task_struct *thread, int desired_prio, int new_prio),
TP_ARGS(thread, desired_prio, new_prio),
TP_STRUCT__entry(
__field(int, proc)
__field(int, thread)
__field(unsigned int, old_prio)
__field(unsigned int, new_prio)
__field(unsigned int, desired_prio)
),
TP_fast_assign(
__entry->proc = thread->tgid;
__entry->thread = thread->pid;
__entry->old_prio = thread->normal_prio;
__entry->new_prio = new_prio;
__entry->desired_prio = desired_prio;
),
TP_printk("proc=%d thread=%d old=%d => new=%d desired=%d",
__entry->proc, __entry->thread, __entry->old_prio,
__entry->new_prio, __entry->desired_prio)
);
TRACE_EVENT(rust_binder_wait_for_work,
TP_PROTO(bool proc_work, bool transaction_stack, bool thread_todo),
TP_ARGS(proc_work, transaction_stack, thread_todo),
TP_STRUCT__entry(
__field(bool, proc_work)
__field(bool, transaction_stack)
__field(bool, thread_todo)
),
TP_fast_assign(
__entry->proc_work = proc_work;
__entry->transaction_stack = transaction_stack;
__entry->thread_todo = thread_todo;
),
TP_printk("proc_work=%d transaction_stack=%d thread_todo=%d",
__entry->proc_work, __entry->transaction_stack,
__entry->thread_todo)
);
TRACE_EVENT(rust_binder_transaction,
TP_PROTO(bool reply, rust_binder_transaction t),
TP_ARGS(reply, t),
TP_STRUCT__entry(
__field(int, debug_id)
__field(int, target_node)
__field(int, from_proc)
__field(int, to_proc)
__field(int, reply)
__field(unsigned int, code)
__field(unsigned int, flags)
),
TP_fast_assign(
rust_binder_thread from_thread = rust_binder_transaction_from_thread(t);
rust_binder_process from = rust_binder_thread_proc(from_thread);
rust_binder_process to = rust_binder_transaction_to_proc(t);
rust_binder_node target_node = rust_binder_transaction_target_node(t);
__entry->debug_id = rust_binder_transaction_debug_id(t);
__entry->target_node = target_node ? rust_binder_node_debug_id(target_node) : 0;
__entry->from_proc = rust_binder_process_task(from)->pid;
__entry->to_proc = rust_binder_process_task(to)->pid;
__entry->reply = reply;
__entry->code = rust_binder_transaction_code(t);
__entry->flags = rust_binder_transaction_flags(t);
),
TP_printk("transaction=%d target_node=%d dest_proc=%d from_proc=%d reply=%d flags=0x%x code=0x%x",
__entry->debug_id, __entry->target_node, __entry->to_proc,
__entry->from_proc, __entry->reply, __entry->flags,
__entry->code)
);
TRACE_EVENT(rust_binder_transaction_thread_selected,
TP_PROTO(rust_binder_transaction t, rust_binder_thread thread),
TP_ARGS(t, thread),
TP_STRUCT__entry(
__field(int, debug_id)
__field(int, to_thread)
),
TP_fast_assign(
__entry->debug_id = rust_binder_transaction_debug_id(t);
__entry->to_thread = rust_binder_thread_id(thread);
),
TP_printk("transaction=%d thread=%d", __entry->debug_id, __entry->to_thread)
);
TRACE_EVENT(rust_binder_transaction_received,
TP_PROTO(rust_binder_transaction t),
TP_ARGS(t),
TP_STRUCT__entry(
__field(int, debug_id)
),
TP_fast_assign(
__entry->debug_id = rust_binder_transaction_debug_id(t);
),
TP_printk("transaction=%d", __entry->debug_id)
);
TRACE_EVENT(rust_binder_transaction_node_send,
TP_PROTO(int t_debug_id, rust_binder_node node,
const struct flat_binder_object *original,
const struct flat_binder_object *translated),
TP_ARGS(t_debug_id, node, original, translated),
TP_STRUCT__entry(
__field(int, debug_id)
__field(int, node_debug_id)
__field(binder_uintptr_t, node_ptr)
__field(int, types)
__field(int, original_handle)
__field(int, translated_handle)
),
TP_fast_assign(
int orig_is_handle = original->hdr.type == BINDER_TYPE_HANDLE || original->hdr.type == BINDER_TYPE_WEAK_HANDLE;
int orig_is_strong = original->hdr.type == BINDER_TYPE_HANDLE || original->hdr.type == BINDER_TYPE_BINDER;
int tran_is_handle = translated->hdr.type == BINDER_TYPE_HANDLE || translated->hdr.type == BINDER_TYPE_WEAK_HANDLE;
int tran_is_strong = translated->hdr.type == BINDER_TYPE_HANDLE || translated->hdr.type == BINDER_TYPE_BINDER;
__entry->debug_id = t_debug_id;
__entry->node_debug_id = rust_binder_node_debug_id(node);
__entry->node_ptr = rust_binder_node_debug_id(node);
__entry->types =
(orig_is_handle << 0) |
(tran_is_handle << 1) |
(orig_is_strong << 2) |
(tran_is_strong << 3);
__entry->original_handle = orig_is_handle ? original->handle : 0;
__entry->translated_handle = tran_is_handle ? original->handle : 0;
),
TP_printk("transaction=%d node=%d ptr=0x%016llx: %s%s [%d] ==> %s%s [%d]",
__entry->debug_id, __entry->node_debug_id,
(u64)__entry->node_ptr,
(__entry->types & (1<<2)) ? "" : "weak ",
(__entry->types & (1<<0)) ? "handle" : "binder",
__entry->original_handle,
(__entry->types & (1<<3)) ? "" : "weak ",
(__entry->types & (1<<1)) ? "handle" : "binder",
__entry->translated_handle)
);
TRACE_EVENT(rust_binder_transaction_fd_send,
TP_PROTO(int t_debug_id, int fd, size_t offset),
TP_ARGS(t_debug_id, fd, offset),
TP_STRUCT__entry(
__field(int, debug_id)
__field(int, fd)
__field(size_t, offset)
),
TP_fast_assign(
__entry->debug_id = t_debug_id;
__entry->fd = fd;
__entry->offset = offset;
),
TP_printk("transaction=%d src_fd=%d offset=%zu",
__entry->debug_id, __entry->fd, __entry->offset)
);
TRACE_EVENT(rust_binder_transaction_fd_recv,
TP_PROTO(int t_debug_id, int fd, size_t offset),
TP_ARGS(t_debug_id, fd, offset),
TP_STRUCT__entry(
__field(int, debug_id)
__field(int, fd)
__field(size_t, offset)
),
TP_fast_assign(
__entry->debug_id = t_debug_id;
__entry->fd = fd;
__entry->offset = offset;
),
TP_printk("transaction=%d dest_fd=%d offset=%zu",
__entry->debug_id, __entry->fd, __entry->offset)
);
TRACE_EVENT(rust_binder_transaction_alloc_buf,
TP_PROTO(int debug_id, const struct binder_transaction_data_sg *data),
TP_ARGS(debug_id, data),
TP_STRUCT__entry(
__field(int, debug_id)
__field(size_t, data_size)
__field(size_t, offsets_size)
__field(size_t, extra_buffers_size)
),
TP_fast_assign(
__entry->debug_id = debug_id;
__entry->data_size = data->transaction_data.data_size;
__entry->offsets_size = data->transaction_data.offsets_size;
__entry->extra_buffers_size = data->buffers_size;
),
TP_printk("transaction=%d data_size=%zd offsets_size=%zd extra_buffers_size=%zd",
__entry->debug_id, __entry->data_size, __entry->offsets_size,
__entry->extra_buffers_size)
);
DECLARE_EVENT_CLASS(rust_binder_buffer_release_class,
TP_PROTO(int debug_id),
TP_ARGS(debug_id),
TP_STRUCT__entry(
__field(int, debug_id)
),
TP_fast_assign(
__entry->debug_id = debug_id;
),
TP_printk("transaction=%d", __entry->debug_id)
);
DEFINE_EVENT(rust_binder_buffer_release_class, rust_binder_transaction_buffer_release,
TP_PROTO(int debug_id),
TP_ARGS(debug_id));
DEFINE_EVENT(rust_binder_buffer_release_class, rust_binder_transaction_failed_buffer_release,
TP_PROTO(int debug_id),
TP_ARGS(debug_id));
DEFINE_EVENT(rust_binder_buffer_release_class, rust_binder_transaction_update_buffer_release,
TP_PROTO(int debug_id),
TP_ARGS(debug_id));
TRACE_EVENT(rust_binder_update_page_range,
TP_PROTO(int pid, bool allocate, size_t start, size_t end),
TP_ARGS(pid, allocate, start, end),
TP_STRUCT__entry(
__field(int, proc)
__field(bool, allocate)
__field(size_t, offset)
__field(size_t, size)
),
TP_fast_assign(
__entry->proc = pid;
__entry->allocate = allocate;
__entry->offset = start;
__entry->size = end - start;
),
TP_printk("proc=%d allocate=%d offset=%zu size=%zu",
__entry->proc, __entry->allocate,
__entry->offset, __entry->size)
);
DECLARE_EVENT_CLASS(rust_binder_lru_page_class,
TP_PROTO(int pid, size_t page_index),
TP_ARGS(pid, page_index),
TP_STRUCT__entry(
__field(int, proc)
__field(size_t, page_index)
),
TP_fast_assign(
__entry->proc = pid;
__entry->page_index = page_index;
),
TP_printk("proc=%d page_index=%zu",
__entry->proc, __entry->page_index)
);
DEFINE_EVENT(rust_binder_lru_page_class, rust_binder_alloc_lru_start,
TP_PROTO(int pid, size_t page_index),
TP_ARGS(pid, page_index));
DEFINE_EVENT(rust_binder_lru_page_class, rust_binder_alloc_lru_end,
TP_PROTO(int pid, size_t page_index),
TP_ARGS(pid, page_index));
DEFINE_EVENT(rust_binder_lru_page_class, rust_binder_free_lru_start,
TP_PROTO(int pid, size_t page_index),
TP_ARGS(pid, page_index));
DEFINE_EVENT(rust_binder_lru_page_class, rust_binder_free_lru_end,
TP_PROTO(int pid, size_t page_index),
TP_ARGS(pid, page_index));
DEFINE_EVENT(rust_binder_lru_page_class, rust_binder_alloc_page_start,
TP_PROTO(int pid, size_t page_index),
TP_ARGS(pid, page_index));
DEFINE_EVENT(rust_binder_lru_page_class, rust_binder_alloc_page_end,
TP_PROTO(int pid, size_t page_index),
TP_ARGS(pid, page_index));
DEFINE_EVENT(rust_binder_lru_page_class, rust_binder_unmap_user_start,
TP_PROTO(int pid, size_t page_index),
TP_ARGS(pid, page_index));
DEFINE_EVENT(rust_binder_lru_page_class, rust_binder_unmap_user_end,
TP_PROTO(int pid, size_t page_index),
TP_ARGS(pid, page_index));
DEFINE_EVENT(rust_binder_lru_page_class, rust_binder_unmap_kernel_start,
TP_PROTO(int pid, size_t page_index),
TP_ARGS(pid, page_index));
DEFINE_EVENT(rust_binder_lru_page_class, rust_binder_unmap_kernel_end,
TP_PROTO(int pid, size_t page_index),
TP_ARGS(pid, page_index));
TRACE_EVENT(rust_binder_command,
TP_PROTO(uint32_t cmd),
TP_ARGS(cmd),
TP_STRUCT__entry(
__field(uint32_t, cmd)
),
TP_fast_assign(
__entry->cmd = cmd;
),
TP_printk("cmd=0x%x %s",
__entry->cmd,
_IOC_NR(__entry->cmd) < ARRAY_SIZE(binder_command_strings) ?
binder_command_strings[_IOC_NR(__entry->cmd)] :
"unknown")
);
TRACE_EVENT(rust_binder_return,
TP_PROTO(uint32_t ret),
TP_ARGS(ret),
TP_STRUCT__entry(
__field(uint32_t, ret)
),
TP_fast_assign(
__entry->ret = ret;
),
TP_printk("ret=0x%x %s",
__entry->ret,
_IOC_NR(__entry->ret) < ARRAY_SIZE(binder_return_strings) ?
binder_return_strings[_IOC_NR(__entry->ret)] :
"unknown")
);
#endif /* _RUST_BINDER_TRACE_H */
/* This part must be outside protection */
#include <trace/define_trace.h>

View File

@@ -6,14 +6,14 @@
* Copyright 2024 Google LLC
*/
#include <linux/rust_binder.h>
#include "rust_binder.h"
#define CREATE_TRACE_POINTS
#define CREATE_RUST_TRACE_POINTS
#include <trace/hooks/vendor_hooks.h>
#include <linux/tracepoint.h>
#include <trace/hooks/rust_binder.h>
#include "rust_binder_hooks.h"
/*
* Export tracepoints that act as a bare tracehook (ie: have no trace event

View File

@@ -0,0 +1,33 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2024 Google, Inc.
*/
#undef TRACE_SYSTEM
#undef TRACE_INCLUDE_FILE
#undef TRACE_INCLUDE_PATH
#define TRACE_SYSTEM rust_binder
#define TRACE_INCLUDE_FILE rust_binder_hooks
#define TRACE_INCLUDE_PATH ../drivers/android/binder
#if !defined(_RUST_BINDER_HOOK_H) || defined(TRACE_HEADER_MULTI_READ)
#define _RUST_BINDER_HOOK_H
#include <trace/hooks/vendor_hooks.h>
/*
* Following tracepoints are not exported in tracefs and provide a
* mechanism for vendor modules to hook and extend functionality
*/
DECLARE_HOOK(android_vh_rust_binder_set_priority,
TP_PROTO(rust_binder_transaction t, struct task_struct *task),
TP_ARGS(t, task));
DECLARE_HOOK(android_vh_rust_binder_restore_priority,
TP_PROTO(struct task_struct *task),
TP_ARGS(task));
#endif /* _RUST_BINDER_HOOK_H */
/* This part must be outside protection */
#include <trace/define_trace.h>

View File

@@ -411,6 +411,14 @@ pub(crate) struct ThreadPrioState {
pub(crate) next: BinderPriority,
}
use core::mem::offset_of;
use kernel::bindings::rb_thread_layout;
pub(crate) const THREAD_LAYOUT: rb_thread_layout = rb_thread_layout {
arc_offset: Arc::<Thread>::DATA_OFFSET,
process: offset_of!(Thread, process),
id: offset_of!(Thread, id),
};
/// This represents a thread that's used with binder.
#[pin_data]
pub(crate) struct Thread {

View File

@@ -2,88 +2,210 @@
// Copyright (C) 2024 Google LLC.
#![allow(unused_variables)]
#![allow(unused_imports)]
use crate::{defs::BinderTransactionDataSg, node::Node, thread::Thread, transaction::Transaction};
use kernel::bindings::{
binder_transaction_data_sg, flat_binder_object, rust_binder_node, rust_binder_thread,
rust_binder_transaction, task_struct,
};
use kernel::error::Result;
use kernel::task::{Pid, Task};
use kernel::tracepoint::declare_trace;
use kernel::uapi::flat_binder_object;
use kernel::uapi;
use core::ffi::{c_int, c_uint, c_ulong};
#[inline]
pub(crate) fn trace_ioctl(cmd: u32, arg: usize) {}
declare_trace! {
unsafe fn rust_binder_ioctl(cmd: c_uint, arg: c_ulong);
unsafe fn rust_binder_ioctl_done(ret: c_int);
unsafe fn rust_binder_read_done(ret: c_int);
unsafe fn rust_binder_write_done(ret: c_int);
unsafe fn rust_binder_set_priority(thread: *mut task_struct, desired_prio: c_int, new_prio: c_int);
unsafe fn android_vh_rust_binder_set_priority(t: rust_binder_transaction, task: *mut task_struct);
unsafe fn android_vh_rust_binder_restore_priority(task: *mut task_struct);
unsafe fn rust_binder_wait_for_work(proc_work: bool, transaction_stack: bool, thread_todo: bool);
unsafe fn rust_binder_transaction(reply: bool, t: rust_binder_transaction);
unsafe fn rust_binder_transaction_received(t: rust_binder_transaction);
unsafe fn rust_binder_transaction_thread_selected(t: rust_binder_transaction, thread: rust_binder_thread);
unsafe fn rust_binder_transaction_node_send(t_debug_id: c_int, n: rust_binder_node,
orig: *const flat_binder_object,
trans: *const flat_binder_object);
unsafe fn rust_binder_transaction_fd_send(t_debug_id: c_int, fd: c_int, offset: usize);
unsafe fn rust_binder_transaction_fd_recv(t_debug_id: c_int, fd: c_int, offset: usize);
unsafe fn rust_binder_transaction_alloc_buf(debug_id: c_int, data: *const binder_transaction_data_sg);
unsafe fn rust_binder_transaction_buffer_release(debug_id: c_int);
unsafe fn rust_binder_transaction_failed_buffer_release(debug_id: c_int);
unsafe fn rust_binder_transaction_update_buffer_release(debug_id: c_int);
unsafe fn rust_binder_update_page_range(pid: c_int, allocate: bool, start: usize, end: usize);
unsafe fn rust_binder_alloc_lru_start(pid: c_int, page_index: usize);
unsafe fn rust_binder_alloc_lru_end(pid: c_int, page_index: usize);
unsafe fn rust_binder_free_lru_start(pid: c_int, page_index: usize);
unsafe fn rust_binder_free_lru_end(pid: c_int, page_index: usize);
unsafe fn rust_binder_alloc_page_start(pid: c_int, page_index: usize);
unsafe fn rust_binder_alloc_page_end(pid: c_int, page_index: usize);
unsafe fn rust_binder_unmap_user_start(pid: c_int, page_index: usize);
unsafe fn rust_binder_unmap_user_end(pid: c_int, page_index: usize);
unsafe fn rust_binder_unmap_kernel_start(pid: c_int, page_index: usize);
unsafe fn rust_binder_unmap_kernel_end(pid: c_int, page_index: usize);
unsafe fn rust_binder_command(cmd: u32);
unsafe fn rust_binder_return(ret: u32);
}
#[inline]
pub(crate) fn trace_ioctl_done(ret: Result) {}
fn raw_transaction(t: &Transaction) -> rust_binder_transaction {
t as *const Transaction as rust_binder_transaction
}
#[inline]
pub(crate) fn trace_read_done(ret: Result) {}
fn raw_thread(t: &Thread) -> rust_binder_thread {
t as *const Thread as rust_binder_thread
}
#[inline]
pub(crate) fn trace_write_done(ret: Result) {}
fn raw_node(n: &Node) -> rust_binder_node {
n as *const Node as rust_binder_node
}
#[inline]
pub(crate) fn trace_set_priority(thread: &Task, desired_prio: c_int, new_prio: c_int) {}
fn to_errno(ret: Result) -> i32 {
match ret {
Ok(()) => 0,
Err(err) => err.to_errno(),
}
}
#[inline]
pub(crate) fn vh_set_priority(t: &Transaction, task: &Task) {}
pub(crate) fn trace_ioctl(cmd: u32, arg: usize) {
// SAFETY: Always safe to call.
unsafe { rust_binder_ioctl(cmd, arg as c_ulong) }
}
#[inline]
pub(crate) fn vh_restore_priority(task: &Task) {}
pub(crate) fn trace_ioctl_done(ret: Result) {
// SAFETY: Always safe to call.
unsafe { rust_binder_ioctl_done(to_errno(ret)) }
}
#[inline]
pub(crate) fn trace_wait_for_work(proc_work: bool, transaction_stack: bool, thread_todo: bool) {}
pub(crate) fn trace_read_done(ret: Result) {
// SAFETY: Always safe to call.
unsafe { rust_binder_read_done(to_errno(ret)) }
}
#[inline]
pub(crate) fn trace_transaction(reply: bool, t: &Transaction) {}
pub(crate) fn trace_write_done(ret: Result) {
// SAFETY: Always safe to call.
unsafe { rust_binder_write_done(to_errno(ret)) }
}
#[inline]
pub(crate) fn trace_transaction_received(t: &Transaction) {}
pub(crate) fn trace_set_priority(thread: &Task, desired_prio: c_int, new_prio: c_int) {
// SAFETY: The pointer to the task is valid for the duration of this call.
unsafe { rust_binder_set_priority(thread.as_ptr(), desired_prio, new_prio) }
}
#[inline]
pub(crate) fn trace_transaction_thread_selected(t: &Transaction, th: &Thread) {}
pub(crate) fn vh_set_priority(t: &Transaction, task: &Task) {
// SAFETY: The pointers to `t` and `task` are valid.
unsafe { android_vh_rust_binder_set_priority(raw_transaction(t), task.as_ptr()) }
}
#[inline]
pub(crate) fn vh_restore_priority(task: &Task) {
// SAFETY: The pointer to `task` is valid.
unsafe { android_vh_rust_binder_restore_priority(task.as_ptr()) }
}
#[inline]
pub(crate) fn trace_wait_for_work(proc_work: bool, transaction_stack: bool, thread_todo: bool) {
// SAFETY: Always safe to call.
unsafe { rust_binder_wait_for_work(proc_work, transaction_stack, thread_todo) }
}
#[inline]
pub(crate) fn trace_transaction(reply: bool, t: &Transaction) {
// SAFETY: The raw transaction is valid for the duration of this call.
unsafe { rust_binder_transaction(reply, raw_transaction(t)) }
}
#[inline]
pub(crate) fn trace_transaction_received(t: &Transaction) {
// SAFETY: The raw transaction is valid for the duration of this call.
unsafe { rust_binder_transaction_received(raw_transaction(t)) }
}
#[inline]
pub(crate) fn trace_transaction_thread_selected(t: &Transaction, th: &Thread) {
// SAFETY: The raw transaction is valid for the duration of this call.
unsafe { rust_binder_transaction_thread_selected(raw_transaction(t), raw_thread(th)) }
}
#[inline]
pub(crate) fn trace_transaction_node_send(
t_debug_id: usize,
n: &Node,
orig: &flat_binder_object,
trans: &flat_binder_object,
orig: &uapi::flat_binder_object,
trans: &uapi::flat_binder_object,
) {
// CAST: Types are identical.
let orig = orig as *const uapi::flat_binder_object as *const flat_binder_object;
// CAST: Types are identical.
let trans = trans as *const uapi::flat_binder_object as *const flat_binder_object;
// SAFETY: The pointers are valid for the duration of this call.
unsafe { rust_binder_transaction_node_send(t_debug_id as c_int, raw_node(n), orig, trans) }
}
#[inline]
pub(crate) fn trace_transaction_fd_send(t_debug_id: usize, fd: u32, offset: usize) {}
pub(crate) fn trace_transaction_fd_send(t_debug_id: usize, fd: u32, offset: usize) {
// SAFETY: This function is always safe to call.
unsafe { rust_binder_transaction_fd_send(t_debug_id as c_int, fd as c_int, offset) }
}
#[inline]
pub(crate) fn trace_transaction_fd_recv(t_debug_id: usize, fd: u32, offset: usize) {}
pub(crate) fn trace_transaction_fd_recv(t_debug_id: usize, fd: u32, offset: usize) {
// SAFETY: This function is always safe to call.
unsafe { rust_binder_transaction_fd_recv(t_debug_id as c_int, fd as c_int, offset) }
}
#[inline]
pub(crate) fn trace_transaction_alloc_buf(debug_id: usize, data: &BinderTransactionDataSg) {
let data = data as *const BinderTransactionDataSg;
// SAFETY: The `data` pointer is valid.
unsafe { rust_binder_transaction_alloc_buf(debug_id as c_int, data.cast()) }
}
#[inline]
pub(crate) fn trace_transaction_buffer_release(debug_id: usize) {}
pub(crate) fn trace_transaction_buffer_release(debug_id: usize) {
// SAFETY: Always safe to call.
unsafe { rust_binder_transaction_buffer_release(debug_id as c_int) }
}
#[inline]
pub(crate) fn trace_transaction_failed_buffer_release(debug_id: usize) {}
pub(crate) fn trace_transaction_failed_buffer_release(debug_id: usize) {
// SAFETY: Always safe to call.
unsafe { rust_binder_transaction_failed_buffer_release(debug_id as c_int) }
}
#[inline]
pub(crate) fn trace_transaction_update_buffer_release(debug_id: usize) {}
pub(crate) fn trace_transaction_update_buffer_release(debug_id: usize) {
// SAFETY: Always safe to call.
unsafe { rust_binder_transaction_update_buffer_release(debug_id as c_int) }
}
#[inline]
pub(crate) fn trace_update_page_range(pid: Pid, allocate: bool, start: usize, end: usize) {}
pub(crate) fn trace_update_page_range(pid: Pid, allocate: bool, start: usize, end: usize) {
// SAFETY: Always safe to call.
unsafe { rust_binder_update_page_range(pid as c_int, allocate, start, end) }
}
macro_rules! define_wrapper_lru_page_class {
($(fn $name:ident;)*) => {$(
kernel::macros::paste! {
#[inline]
pub(crate) fn [< trace_ $name >](pid: Pid, page_index: usize) {
// SAFETY: Always safe to call.
unsafe { [< rust_binder_ $name >](pid as c_int, page_index) }
}
}
)*}
@@ -103,7 +225,13 @@ define_wrapper_lru_page_class! {
}
#[inline]
pub(crate) fn trace_command(cmd: u32) {}
pub(crate) fn trace_command(cmd: u32) {
// SAFETY: Trivially safe to call with primitive u32.
unsafe { rust_binder_command(cmd) }
}
#[inline]
pub(crate) fn trace_return(ret: u32) {}
pub(crate) fn trace_return(ret: u32) {
// SAFETY: Trivially safe to call with primitive u32.
unsafe { rust_binder_return(ret) }
}

View File

@@ -25,6 +25,17 @@ use crate::{
BinderReturnWriter, DArc, DLArc, DTRWrap, DeliverToRead,
};
use core::mem::offset_of;
use kernel::bindings::rb_transaction_layout;
pub(crate) const TRANSACTION_LAYOUT: rb_transaction_layout = rb_transaction_layout {
debug_id: offset_of!(Transaction, debug_id),
code: offset_of!(Transaction, code),
flags: offset_of!(Transaction, flags),
from_thread: offset_of!(Transaction, from),
to_proc: offset_of!(Transaction, to),
target_node: offset_of!(Transaction, target_node),
};
#[pin_data(PinnedDrop)]
pub(crate) struct Transaction {
pub(crate) debug_id: usize,

View File

@@ -58,3 +58,9 @@ const blk_features_t RUST_CONST_HELPER_BLK_FEAT_ROTATIONAL = BLK_FEAT_ROTATIONAL
const size_t RUST_CONST_HELPER_ASHMEM_NAME_PREFIX_LEN = ASHMEM_NAME_PREFIX_LEN;
const size_t RUST_CONST_HELPER_ASHMEM_FULL_NAME_LEN = ASHMEM_FULL_NAME_LEN;
#endif
#if IS_ENABLED(CONFIG_ANDROID_BINDER_IPC_RUST)
#include "../../drivers/android/binder/rust_binder.h"
#include "../../drivers/android/binder/rust_binder_hooks.h"
#include "../../drivers/android/binder/rust_binder_events.h"
#endif

View File

@@ -206,6 +206,9 @@ impl<T> Arc<T> {
// `Arc` object.
Ok(unsafe { Self::from_inner(KBox::leak(inner).into()) })
}
/// The offset that the value is stored at.
pub const DATA_OFFSET: usize = core::mem::offset_of!(ArcInner<T>, data);
}
impl<T: ?Sized> Arc<T> {