linux_syscalls/env/aux/
mod.rs

1use core::ffi::c_void;
2
3#[cfg_attr(
4    any(target_arch = "powerpc", target_arch = "powerpc64"),
5    path = "powerpc.rs"
6)]
7#[cfg_attr(any(target_arch = "x86", target_arch = "x86_64"), path = "x86.rs")]
8#[cfg_attr(target_arch = "arm", path = "arm.rs")]
9#[cfg_attr(target_arch = "aarch64", path = "aarch64.rs")]
10#[cfg_attr(target_arch = "loongarch64", path = "loongarch64.rs")]
11#[cfg_attr(target_arch = "s390x", path = "s390x.rs")]
12#[cfg_attr(any(target_arch = "mips", target_arch = "mips64"), path = "mips.rs")]
13#[cfg_attr(
14    any(target_arch = "riscv32", target_arch = "riscv64"),
15    path = "riscv.rs"
16)]
17mod arch;
18
19pub use arch::{Features, Features2};
20
21#[cfg(target_pointer_width = "32")]
22#[allow(non_camel_case_types)]
23type aux_t = u32;
24#[cfg(target_pointer_width = "64")]
25#[allow(non_camel_case_types)]
26type aux_t = u64;
27
28#[repr(C)]
29struct AuxvPair {
30    pub a_type: aux_t,
31    pub a_un: aux_t,
32}
33
34mod __sealed {
35    pub trait Sealed {}
36}
37use __sealed::Sealed;
38
39#[doc(hidden)]
40pub trait AuxValue: Sealed {
41    fn from(value: aux_t) -> Self;
42}
43
44/// A trait representing a valid key for [crate::env::getauxval] function.
45pub trait VdsoKey: Sealed {
46    const ID: aux_t;
47    const N: usize;
48    type Item: AuxValue;
49}
50
51impl Sealed for i32 {}
52impl AuxValue for i32 {
53    #[inline]
54    fn from(value: aux_t) -> Self {
55        value as Self
56    }
57}
58
59impl Sealed for *const c_void {}
60impl AuxValue for *const c_void {
61    #[inline]
62    fn from(value: aux_t) -> Self {
63        value as Self
64    }
65}
66
67impl Sealed for *const u8 {}
68impl AuxValue for *const u8 {
69    #[inline]
70    fn from(value: aux_t) -> Self {
71        value as Self
72    }
73}
74
75impl Sealed for *const [u8; 16] {}
76impl AuxValue for *const [u8; 16] {
77    #[inline]
78    fn from(value: aux_t) -> Self {
79        value as Self
80    }
81}
82
83impl Sealed for usize {}
84impl AuxValue for usize {
85    #[inline]
86    fn from(value: aux_t) -> Self {
87        value as usize
88    }
89}
90
91impl Sealed for bool {}
92impl AuxValue for bool {
93    #[inline]
94    fn from(value: aux_t) -> Self {
95        value != 0
96    }
97}
98
99impl Sealed for u32 {}
100impl AuxValue for u32 {
101    #[inline]
102    #[allow(clippy::unnecessary_cast)]
103    fn from(value: aux_t) -> Self {
104        value as u32
105    }
106}
107
108macro_rules! def_keys {
109    (__internal_def ($no:expr) $(#[$meta:meta])* $name:ident($n:literal) -> $ty:ty $(,)?) => {
110        def_keys!(__decl_def ($no) $(#[$meta])* $name($n) -> $ty);
111        const KEYS_LEN: usize = $no+1;
112    };
113    (__internal_def ($no:expr) $(#[$meta:meta])* $name:ident($n:literal) -> $ty:ty, $($rest:tt)+) => {
114        def_keys!(__decl_def ($no) $(#[$meta])* $name($n) -> $ty);
115        def_keys!(__internal_def ($no+1) $($rest)+);
116    };
117    (__decl_def ($no:expr) $(#[$meta:meta])* $name:ident($n:literal) -> $ty:ty) => {
118        $(#[$meta])*
119        #[non_exhaustive]
120        pub struct $name;
121        impl Sealed for $name {}
122        impl VdsoKey for $name {
123            const ID: aux_t = $n;
124            const N: usize = $no;
125            type Item = $ty;
126        }
127    };
128    (__internal_match $($(#[$meta:meta])* $name:ident($n:literal) -> $ty:ty),+ $(,)?) => {
129        #[inline]
130        pub(crate) unsafe fn init(ptr: *const ())  {
131            let mut ptr = ptr as *mut AuxvPair;
132
133            while (*ptr).a_type != 0 {
134                #[deny(unreachable_patterns)]
135                match (*ptr).a_type {
136                $(
137                    $name::ID => {
138                        *AUXV.get_unchecked_mut($name::N) = Some((*ptr).a_un);
139                    }
140                )+
141                    _ => (),
142                }
143                ptr = ptr.add(1);
144            }
145        }
146    };
147    ($($rest:tt)+) => {
148        def_keys!(__internal_def (0) $($rest)+);
149        def_keys!(__internal_match $($rest)+);
150    }
151}
152
153def_keys! {
154    /// File descriptor of program (AT_EXECFD).
155    ExecFd(2) -> i32,
156    /// Program headers for program (AT_PHDR).
157    ProgramHeader(3) -> *const c_void,
158    /// Size of program header entry (AT_PHENT).
159    ProgramHeaderSize(4) -> usize,
160    /// Number of program headers (AT_PHNUM).
161    ProgramHeadersNumber(5) -> usize,
162    /// System page size (AT_PAGESZ).
163    PageSize(6) -> usize,
164    /// Base address of interpreter (AT_BASE).
165    BaseAddress(7) -> *const c_void,
166    /// Flags (AT_FLAGS).
167    Flags(8) -> usize,
168    /// Entry point of program (AT_ENTRY).
169    EntryPoint(9) -> *const c_void,
170    /// Program is not ELF (AT_NOTELF).
171    NotElf(10) -> bool,
172    /// Real uid (AT_UID).
173    Uid(11) -> u32,
174    /// Effective uid (AT_EUID).
175    Euid(12) -> u32,
176    /// Real gid (AT_GID).
177    Gid(13) -> u32,
178    /// Effective gid (AT_EGID).
179    Egid(14) -> u32,
180    /// String identifying CPU for optimizations (AT_PLATFORM).
181    Platform(15) -> *const u8,
182    /// Arch dependent hints at CPU capabilities (AT_HWCAP).
183    HardwareCapabilities(16) -> Features,
184    /// Frequency at which times() increments (AT_CLKTCK).
185    ClockFrequency(17) -> usize,
186    /// the data cache block size (AT_DCACHEBSIZE).
187    DCacheBSize(19) -> usize,
188    /// the instruction cache block size (AT_ICACHEBSIZE).
189    ICacheBSize(20) -> usize,
190    /// the unified cache block size (AT_UCACHEBSIZE).
191    UCacheBSize(21) -> usize,
192    /// Secure mode boolean (AT_SECURE).
193    Secure(23) -> bool,
194    /// String identifying real platform, may differ from AT_PLATFORM (AT_BASE_PLATFORM).
195    BasePlatform(24) -> *const u8,
196    /// Address of 16 random bytes (AT_RANDOM).
197    Random(25) -> *const [u8; 16],
198    /// Extension of AT_HWCAP (AT_HWCAP2).
199    HardwareCapabilities2(26) -> Features2,
200    /// Rseq supported feature size (AT_RSEQ_FEATURE_SIZE).
201    RSeqFeatureSize(27) -> usize,
202    /// Rseq allocation alignment (AT_RSEQ_ALIGN).
203    RSeqAlign(28) -> usize,
204    /// Filename of program (AT_EXECFN).
205    Filename(31) -> *const u8,
206    /// The entry point to the system call function in the vDSO.
207    /// Not present/needed on all architectures (e.g., absent on x86-64).
208    /// (AT_SYSINFO)
209    SysInfo(32) -> *const c_void,
210    /// The address of a page containing the virtual Dynamic Shared
211    /// Object (vDSO) that the kernel creates in order to provide fast
212    /// implementations of certain system calls. (AT_SYSINFO_EHDR)
213    SysInfoHeader(33) -> *const c_void,
214    /// The L1 instruction cache size (AT_L1I_CACHESIZE).
215    L1ICacheSize(40) -> usize,
216    /// Geometry of the L1 instruction cache, encoded as for
217    /// AT_L1D_CACHEGEOMETRY (AT_L1I_CACHEGEOMETRY).
218    L1ICacheGeometry(41) -> usize,
219    /// The L1 data cache size (AT_L1D_CACHESIZE).
220    L1DCacheSize(42) -> usize,
221    // Geometry of the L1 data cache, encoded with the cache line size
222    // in bytes in the bottom 16 bits and the cache associativity in
223    // the next 16 bits.  The associativity is such that if N is the
224    // 16-bit value, the cache is N-way set associative. (AT_L1D_CACHEGEOMETRY)
225    L1DCacheGeometry(43) -> usize,
226    /// The L2 cache size (AT_L2_CACHESIZE).
227    L2CacheSize(44) -> usize,
228    /// Geometry of the L2 cache, encoded as for AT_L1D_CACHEGEOMETRY (AT_L2_CACHEGEOMETRY).
229    L2CacheGeometry(45) -> usize,
230    /// The L3 cache size (AT_L3_CACHESIZE).
231    L3CacheSize(46) -> usize,
232    /// Geometry of the L3 cache, encoded as for AT_L1D_CACHEGEOMETRY (AT_L3_CACHEGEOMETRY).
233    L3CacheGeometry(47) -> usize,
234    /// (AT_ADI_BLKSZ)
235    ADIBlockSize(48) -> usize,
236    /// (AT_ADI_NBITS)
237    ADINBits(49) -> usize,
238    /// (AT_ADI_UEONADI)
239    ADIUEOnADI(50) -> usize,
240    /// Minimal stack size for signal delivery (AT_MINSIGSTKSZ).
241    MinimalSignalStackSize(51) -> usize,
242}
243
244pub(crate) static mut AUXV: [Option<aux_t>; KEYS_LEN] = [None; KEYS_LEN];
245
246#[inline]
247pub(crate) unsafe fn get<T: VdsoKey>() -> Option<T::Item> {
248    AUXV.get_unchecked(T::N).map(<T::Item as AuxValue>::from)
249}