• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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