blob: 0c02480d70084859ad4a97ea238b5bce832eb8e1 [file] [log] [blame] [edit]
#!/usr/bin/env fuchsia-vendored-python
#
# Copyright 2023 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import sys
# Add //build/rust to Python path so bindgen import works.
FUCHSIA_DIR = os.environ.get(
"FUCHSIA_DIR",
os.path.join(os.path.dirname(__file__), "..", "..", "..", ".."),
)
sys.path.append(os.path.join(FUCHSIA_DIR, "build", "rust"))
from bindgen import Bindgen
RELATIVE_SCRIPT_PATH = os.path.relpath(__file__, FUCHSIA_DIR)
MODULE_DOC_COMMENT = f"""
//! WARNING - This file was auto generated by //{RELATIVE_SCRIPT_PATH}.
//! Do not modify this file. To re-generate, run the following command from the root of
//! your Fuchsia checkout:
//!
//! ./{RELATIVE_SCRIPT_PATH}
"""
RAW_LINES = (
MODULE_DOC_COMMENT
+ """
use zerocopy::{IntoBytes, FromBytes, KnownLayout, Immutable};
use crate::fscrypt_key_specifier;
"""
)
for s in [8, 16, 144, 272]:
RAW_LINES += (
"""
// SAFETY: The IntoBytes implementation is safe because the array size is a
// multiple of 8, so there is no padding.
unsafe impl IntoBytes for __BindgenOpaqueArray8<[u8; %dusize]> {
fn only_derive_is_allowed_to_implement_this_trait() {
}
}
"""
% s
)
PTR_TYPES = """
#[repr(transparent)]
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, IntoBytes, FromBytes, KnownLayout, Immutable)]
pub struct uaddr {
pub addr: u64,
}
#[derive(Debug, Default, Eq, PartialEq, Hash, Ord, PartialOrd, IntoBytes, FromBytes, KnownLayout, Immutable)]
#[repr(transparent)]
pub struct uref<T> {
pub addr: uaddr,
_phantom: std::marker::PhantomData<T>,
}
impl<T> Copy for uref<T> {}
impl<T> Clone for uref<T> {
fn clone(&self) -> Self {
Self { addr: self.addr, _phantom: Default::default() }
}
}
impl<T> From<uaddr> for uref<T> {
fn from(addr: uaddr) -> Self {
Self { addr, _phantom: Default::default() }
}
}
#[repr(transparent)]
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, IntoBytes, FromBytes, KnownLayout, Immutable)]
pub struct uaddr32 {
pub addr: u32,
}
impl From<uaddr32> for uaddr {
fn from(addr32: uaddr32) -> Self {
Self { addr: addr32.addr.into() }
}
}
impl TryFrom<uaddr> for uaddr32 {
type Error = ();
fn try_from(addr: uaddr) -> Result<Self, ()> {
Ok(Self { addr: addr.addr.try_into().map_err(|_| ())? })
}
}
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, IntoBytes, FromBytes, KnownLayout, Immutable)]
#[repr(transparent)]
pub struct uref32<T> {
pub addr: uaddr32,
_phantom: std::marker::PhantomData<T>,
}
impl<T> From<uaddr32> for uref32<T> {
fn from(addr: uaddr32) -> Self {
Self { addr, _phantom: Default::default() }
}
}
impl<T> From<uaddr32> for uref<T> {
fn from(addr: uaddr32) -> Self {
Self { addr: addr.into(), _phantom: Default::default() }
}
}
impl<T> From<uref32<T>> for uref<T> {
fn from(ur: uref32<T>) -> Self {
Self { addr: ur.addr.into(), _phantom: Default::default() }
}
}
impl<T> TryFrom<uref<T>> for uref32<T> {
type Error = ();
fn try_from(ur: uref<T>) -> Result<Self, ()> {
Ok(Self { addr: ur.addr.try_into().map_err(|_| ())?, _phantom: Default::default() })
}
}
"""
# Tell bindgen not to produce records for these types.
OPAQUE_TYPES = [
"group_filter.*",
"sigval",
"StdAtomic.*",
]
# Cross-architecture include paths (the ArchInfo class also has an arch-specific one to add).
INCLUDE_DIRS = [
"third_party/android/platform/bionic/libc/kernel/uapi",
"third_party/android/platform/bionic/libc/kernel/android/uapi",
"src/starnix/lib/linux_uapi/stub",
]
STD_DERIVES = [
"default",
]
# Additional traits that should be added to types matching the regexps.
AUTO_DERIVE_TRAITS = [
(
r"__BindgenBitfieldUnit",
["Immutable", "IntoBytes", "KnownLayout", "FromBytes"],
),
(
r"__IncompleteArrayField",
["Clone", "IntoBytes", "FromBytes", "KnownLayout", "Immutable"],
),
(
r"__BindgenUnionField",
["IntoBytes", "FromBytes", "KnownLayout", "Immutable"],
),
(
r"__BindgenOpaqueArray$",
["IntoBytes", "FromBytes", "KnownLayout", "Immutable"],
),
(
r"__BindgenOpaqueArray8$",
["FromBytes", "KnownLayout", "Immutable"],
),
(
r"__sifields__bindgen_ty_(2|3|7)",
["IntoBytes", "FromBytes", "KnownLayout", "Immutable"],
),
(
r"audit_status.*",
["Copy", "Clone", "FromBytes", "IntoBytes", "KnownLayout", "Immutable"],
),
(r"binder_fd_object.*", ["KnownLayout", "FromBytes", "Immutable"]),
(
r"binder_transaction_data__bindgen_ty_2__bindgen_ty_1",
["IntoBytes", "FromBytes", "KnownLayout", "Immutable"],
),
(r"binder_transaction_data.*", ["KnownLayout", "FromBytes", "Immutable"]),
(
r"bpf_attr__bindgen_ty_(1|3|5|6|7|8|9|10|11|12|13|16|17|18|19)(_.+)?$",
["IntoBytes", "FromBytes", "KnownLayout", "Immutable"],
),
(r"bpf_attr.*", ["KnownLayout", "FromBytes", "Immutable"]),
(
r"bpf_insn",
["KnownLayout", "IntoBytes", "FromBytes", "Immutable", "PartialEq"],
),
(
r"bpf_prog",
["Copy", "Clone", "IntoBytes", "FromBytes", "KnownLayout", "Immutable"],
),
(r"bpf_sockopt", ["KnownLayout", "IntoBytes", "FromBytes", "Immutable"]),
(r"bpf_sock_addr", ["KnownLayout", "IntoBytes", "FromBytes", "Immutable"]),
(r"flat_binder_object.*", ["KnownLayout", "FromBytes", "Immutable"]),
(
r"usb_functionfs_event.*",
["KnownLayout", "Clone", "IntoBytes", "FromBytes", "Immutable"],
),
(
r"fuse_dirent",
["KnownLayout", "Clone", "IntoBytes", "FromBytes", "Immutable"],
),
(
r"fuse_open_out.*",
["KnownLayout", "Clone", "IntoBytes", "FromBytes", "Immutable"],
),
(
r"fuse_open_out$",
["Debug"],
),
(
r"fuse_in_header.*",
["KnownLayout", "Clone", "IntoBytes", "FromBytes", "Immutable"],
),
(
r"fuse_in_header$",
["Debug"],
),
(r"ifreq.*", ["KnownLayout", "FromBytes", "Immutable"]),
(r"if_settings.*", ["KnownLayout", "FromBytes", "Immutable"]),
(r"in6_addr", ["IntoBytes", "FromBytes", "KnownLayout", "Immutable"]),
(r"in6_pktinfo", ["IntoBytes", "FromBytes", "KnownLayout", "Immutable"]),
(r"inotify_event", ["KnownLayout", "IntoBytes", "Immutable"]),
(r"dm_name_list", ["KnownLayout", "IntoBytes", "Immutable", "FromBytes"]),
(
r"dm_target_versions",
["KnownLayout", "IntoBytes", "Immutable", "FromBytes"],
),
(
r"fsverity_digest",
["KnownLayout", "Clone", "IntoBytes", "Immutable", "FromBytes"],
),
(r"fscrypt_add_key_arg", ["KnownLayout", "FromBytes", "Immutable"]),
(r"fscrypt_remove_key_arg", ["KnownLayout", "FromBytes", "Immutable"]),
(r"fscrypt_key_specifier", ["KnownLayout", "FromBytes", "Immutable"]),
(
r"fscrypt_key_specifier__bindgen_ty_1",
["KnownLayout", "FromBytes", "Immutable"],
),
(
r"input_event",
["KnownLayout", "IntoBytes", "FromBytes", "Immutable", "PartialEq"],
),
(
r"input_id",
["KnownLayout", "IntoBytes", "FromBytes", "Immutable", "PartialEq"],
),
(r"ip6t_ip6", ["IntoBytes", "FromBytes", "KnownLayout", "Immutable"]),
(r"ip6?t_entry", ["IntoBytes", "FromBytes", "KnownLayout", "Immutable"]),
(r"ip6?t_reject*", ["IntoBytes", "FromBytes", "KnownLayout", "Immutable"]),
(r"ip6?t_get_entries", ["KnownLayout", "FromBytes", "Immutable"]),
(r"ip6?t_replace", ["IntoBytes", "FromBytes", "KnownLayout", "Immutable"]),
(
r"__kernel_sigaction.*",
["IntoBytes", "FromBytes", "KnownLayout", "Immutable"],
),
(r"nf_.*", ["KnownLayout", "FromBytes", "Immutable"]),
(r"perf_event_attr", ["FromBytes", "Immutable"]),
(r"perf_event_mmap_page", ["IntoBytes", "Immutable"]),
(r"robust_list_head", ["KnownLayout", "FromBytes", "Immutable"]),
(r"robust_list", ["KnownLayout", "FromBytes", "Immutable"]),
(r"sigevent", ["KnownLayout", "FromBytes", "Immutable"]),
(r"sigval", ["KnownLayout", "IntoBytes", "FromBytes", "Immutable"]),
(r"__sk_buff", ["KnownLayout", "IntoBytes", "FromBytes", "Immutable"]),
(r"sockaddr_in", ["KnownLayout", "IntoBytes", "FromBytes", "Immutable"]),
(r"sockaddr_ll", ["KnownLayout", "IntoBytes", "FromBytes", "Immutable"]),
(r"sock_fprog", ["KnownLayout", "FromBytes", "Immutable"]),
(r"sysinfo", ["KnownLayout", "IntoBytes", "Immutable"]),
(
r"timeval",
["KnownLayout", "IntoBytes", "FromBytes", "Immutable", "PartialEq"],
),
(r"xt_counters_info", ["KnownLayout", "FromBytes", "Immutable"]),
(r"xt_bpf_info_v1", ["KnownLayout", "FromBytes", "IntoBytes", "Immutable"]),
(r"xt_tproxy_target_info_v1", ["KnownLayout", "FromBytes", "Immutable"]),
(r"fastrpc_.*", ["IntoBytes, FromBytes, KnownLayout, Immutable"]),
(r"remote_.*", ["IntoBytes, FromBytes, KnownLayout, Immutable"]),
(
r"ucred",
[
"KnownLayout",
"IntoBytes",
"FromBytes",
"Immutable",
"Eq",
"PartialEq",
],
),
(
r"cmsghdr",
[
"KnownLayout",
"IntoBytes",
"FromBytes",
"Immutable",
"Eq",
"PartialEq",
],
),
]
# General replacements to apply to the contents of the file. These are tuples of
# compiled regular expressions + the thing to replace matches with.
REPLACEMENTS = [
# Use CStr to represent constant C strings. The inputs look like:
# pub const FS_KEY_DESC_PREFIX: &[u8; 9usize] = b"fscrypt:\0";
(
r': &\[u8; [0-9]+(usize)?\] = b"(.*)\\0";\n',
': &\'static std::ffi::CStr = c"\\2";\n',
),
# Change `__IncompleteArrayField` representation to `transparent`, which is necessary to
# allow it to derive `IntoBytes`.
# TODO(https://github.com/google/zerocopy/issues/10): Remove this once zerocopy is updated
# to allow `IntoBytes` for generic structs with `repr(C)`.
(
r"#\[repr\(C\)\]\n"
r"#\[derive\((([A-Za-z]+, )*[A-Za-z]+)\)\]\n"
r"pub struct (__IncompleteArrayField|__BindgenUnionField)",
"""#[repr(transparent)]
#[derive(\\1)]
pub struct \\3""",
),
# Add IntoBytes/FromBytes/KnownLayout/Immutable to every copyable struct regardless of
# name.
# TODO(https://github.com/rust-lang/rust-bindgen/issues/2170):
# Remove in favor of bindgen support for custom derives.
(
r"\n#\[derive\(Debug, Default, Copy, Clone(, FromBytes)?\)\]\n",
"\n#[derive(Debug, Default, Copy, Clone, IntoBytes, FromBytes, KnownLayout, Immutable)]\n",
),
(
r"\n#\[derive\(Debug, Copy, Clone(, FromBytes)?\)\]\n",
"\n#[derive(Debug, Copy, Clone, IntoBytes, FromBytes, KnownLayout, Immutable)]\n",
),
# Convert atomic wrapper.
(r": StdAtomic([UI])(8|16|32|64)", ": std::sync::atomic::Atomic\\1\\2"),
# Remove __bindgen_missing from the start of constants defined in missing_includes.h
(r"const __bindgen_missing_([a-zA-Z_0-9]+)", "const \\1"),
# Convert atomic wrapper.
(r": StdAtomic([UI])(8|16|32|64)", ": std::sync::atomic::Atomic\\1\\2"),
# Remove __bindgen_missing from the start of constants defined in missing_includes.h
(r"const __bindgen_missing_([a-zA-Z_0-9]+)", "const \\1"),
# Workaround for https://github.com/rust-lang/rust-bindgen/issues/3068.
(r"pub __bindgen_padding_0: \[u8; 1844[0-9]+usize\],\n", ""),
]
REPLACEMENTS_PTR = [
# Use uaddr/uref in place of pointers for compat with zerocopy traits. Because
# the target of the pointer is in userspace anyway, treating it as an opaque
# pointer is harmless.
(r"\*(const|mut) crate::types::c_void", "uaddr"),
(
r'::std::option::Option<unsafe extern "C" fn\([a-zA-Z_0-9: ]*\)>',
"uaddr",
),
(r"([:=]) \*(const|mut) ([a-z_][a-zA-Z_0-9:]*)", "\\1 uref<\\3>"),
]
ARCH32_REPLACEMENTS_PTR = [
# Use uaddr/uref in place of pointers for compat with zerocopy traits. Because
# the target of the pointer is in userspace anyway, treating it as an opaque
# pointer is harmless.
# For arch32, we only use 64-bit width when dealing with AsBytes union
# padding.
(r"\*(const|mut) crate::types::arch32::c_void", "crate::uaddr32"),
(
r'::std::option::Option<\s*unsafe extern "C" fn\([*a-zA-Z_0-9,:\s]*\),?\s*>',
"crate::uaddr32",
),
(r"([:=]) \*(const|mut) ([a-z_][a-zA-Z_0-9:]*)", "\\1 crate::uref32<\\3>"),
(
r"pub _u: __kernel_sigaction__bindgen_ty_1,",
"pub sa_handler: __sighandler_t,",
),
]
INPUT_FILE = "src/starnix/lib/linux_uapi/wrapper.h"
NO_DEBUG_TYPES = [
"__sifields__bindgen_ty_(2|3)",
]
NO_COPY_TYPES = [
"StdAtomic.*",
]
# Bindgen offers limited support for union types. The fscrypt_key_specifier__bindgen_ty_1 union has
# three fields that bindgen defines to be three different sizes. As a result, the union is
# prevented from implementing the IntoBytes trait which prevents the larger fscrypt_add_key_arg
# struct from implementing IntoBytes. manual.rs adds the appropriate padding to the union fields
# so that it and thus fscrypt_add_key_arg can implement the IntoBytes trait.
TYPE_BLOCKLIST = [
"fscrypt_key_specifier",
"fscrypt_key_specifier__bindgen_ty_1",
"fscrypt_add_key_arg",
"fscrypt_descriptor",
"fscrypt_identifier",
]
class ArchInfo:
def __init__(self, name, clang_target, include):
self.name = name # Our internal arch name.
self.clang_target = clang_target # Clang "triple" name for this arch.
self.include = (
include # Include directory for the arch-specific uapi files.
)
ARCH_INFO = [
ArchInfo(
"x86_64",
"x86_64-pc-linux-gnu",
"third_party/android/platform/bionic/libc/kernel/uapi/asm-x86",
),
ArchInfo(
"arm64",
"aarch64-linux-gnu",
"third_party/android/platform/bionic/libc/kernel/uapi/asm-arm64",
),
ArchInfo(
"arm",
"arm-linux-gnueabihf",
"third_party/android/platform/bionic/libc/kernel/uapi/asm-arm",
),
ArchInfo(
"riscv64",
"riscv64-linux-gnu",
"third_party/android/platform/bionic/libc/kernel/uapi/asm-riscv",
),
]
bindgen = Bindgen()
bindgen.opaque_types = OPAQUE_TYPES
bindgen.std_derives = STD_DERIVES
bindgen.set_auto_derive_traits(AUTO_DERIVE_TRAITS)
bindgen.ignore_functions = True
bindgen.type_blocklist = TYPE_BLOCKLIST
bindgen.no_debug_types = NO_DEBUG_TYPES
bindgen.no_copy_types = NO_COPY_TYPES
bindgen.enable_stdlib_include_dirs = False
bindgen.size_t_is_usize = False
for arch in ARCH_INFO:
bindgen.raw_lines = RAW_LINES
if arch.name == "arm":
bindgen.c_types_prefix = "crate::types::arch32"
bindgen.set_replacements(REPLACEMENTS + ARCH32_REPLACEMENTS_PTR)
else:
bindgen.c_types_prefix = "crate::types"
bindgen.set_replacements(REPLACEMENTS + REPLACEMENTS_PTR)
bindgen.raw_lines += PTR_TYPES
bindgen.clang_target = arch.clang_target
bindgen.include_dirs = INCLUDE_DIRS + [arch.include]
rust_file = "src/starnix/lib/linux_uapi/src/" + arch.name + ".rs"
bindgen.run(INPUT_FILE, rust_file)