1 //! Linux auxv support, using libc.
2 //!
3 //! # Safety
4 //!
5 //! This uses raw pointers to locate and read the kernel-provided auxv array.
6 #![allow(unsafe_code)]
7
8 use super::super::elf::*;
9 #[cfg(feature = "param")]
10 use crate::ffi::CStr;
11 #[cfg(feature = "runtime")]
12 use core::slice;
13
14 // `getauxval` wasn't supported in glibc until 2.16.
15 weak!(fn getauxval(libc::c_ulong) -> *mut libc::c_void);
16
17 #[cfg(feature = "param")]
18 #[inline]
page_size() -> usize19 pub(crate) fn page_size() -> usize {
20 unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }
21 }
22
23 #[cfg(feature = "param")]
24 #[inline]
clock_ticks_per_second() -> u6425 pub(crate) fn clock_ticks_per_second() -> u64 {
26 unsafe { libc::sysconf(libc::_SC_CLK_TCK) as u64 }
27 }
28
29 #[cfg(feature = "param")]
30 #[inline]
linux_hwcap() -> (usize, usize)31 pub(crate) fn linux_hwcap() -> (usize, usize) {
32 if let Some(libc_getauxval) = getauxval.get() {
33 unsafe {
34 let hwcap = libc_getauxval(libc::AT_HWCAP) as usize;
35 let hwcap2 = libc_getauxval(libc::AT_HWCAP2) as usize;
36 (hwcap, hwcap2)
37 }
38 } else {
39 (0, 0)
40 }
41 }
42
43 #[cfg(feature = "param")]
44 #[inline]
linux_execfn() -> &'static CStr45 pub(crate) fn linux_execfn() -> &'static CStr {
46 if let Some(libc_getauxval) = getauxval.get() {
47 unsafe { CStr::from_ptr(libc_getauxval(libc::AT_EXECFN).cast()) }
48 } else {
49 cstr!("")
50 }
51 }
52
53 #[cfg(feature = "runtime")]
54 #[inline]
exe_phdrs() -> (*const libc::c_void, usize)55 pub(crate) fn exe_phdrs() -> (*const libc::c_void, usize) {
56 unsafe {
57 (
58 libc::getauxval(libc::AT_PHDR) as *const libc::c_void,
59 libc::getauxval(libc::AT_PHNUM) as usize,
60 )
61 }
62 }
63
64 #[cfg(feature = "runtime")]
65 #[inline]
exe_phdrs_slice() -> &'static [Elf_Phdr]66 pub(in super::super) fn exe_phdrs_slice() -> &'static [Elf_Phdr] {
67 let (phdr, phnum) = exe_phdrs();
68
69 // Safety: We assume the `AT_PHDR` and `AT_PHNUM` values provided by the
70 // kernel form a valid slice.
71 unsafe { slice::from_raw_parts(phdr.cast(), phnum) }
72 }
73
74 /// `AT_SYSINFO_EHDR` isn't present on all platforms in all configurations,
75 /// so if we don't see it, this function returns a null pointer.
76 #[inline]
sysinfo_ehdr() -> *const Elf_Ehdr77 pub(in super::super) fn sysinfo_ehdr() -> *const Elf_Ehdr {
78 if let Some(libc_getauxval) = getauxval.get() {
79 unsafe { libc_getauxval(linux_raw_sys::general::AT_SYSINFO_EHDR.into()) as *const Elf_Ehdr }
80 } else {
81 core::ptr::null()
82 }
83 }
84