#![allow(unsafe_code)]
use super::super::c;
use super::super::elf::Elf_Phdr;
use crate::ffi::ZStr;
use core::mem::size_of;
use core::slice;
use linux_raw_sys::general::{
AT_CLKTCK, AT_EXECFN, AT_HWCAP, AT_HWCAP2, AT_NULL, AT_PAGESZ, AT_PHDR, AT_PHENT, AT_PHNUM,
AT_SYSINFO_EHDR,
};
#[inline]
pub(crate) fn page_size() -> usize {
auxv().page_size
}
#[inline]
pub(crate) fn clock_ticks_per_second() -> u64 {
auxv().clock_ticks_per_second as u64
}
#[inline]
pub(crate) fn linux_hwcap() -> (usize, usize) {
let auxv = auxv();
(auxv.hwcap, auxv.hwcap2)
}
#[inline]
pub(crate) fn linux_execfn() -> &'static ZStr {
unsafe { ZStr::from_ptr(auxv().execfn as *const _) }
}
#[inline]
pub(crate) fn exe_phdrs() -> (*const c::c_void, usize) {
let auxv = auxv();
(auxv.phdr as *const c::c_void, auxv.phnum)
}
#[inline]
pub(in super::super) fn exe_phdrs_slice() -> &'static [Elf_Phdr] {
let (ptr, len) = exe_phdrs();
unsafe { slice::from_raw_parts(ptr.cast(), len) }
}
#[inline]
pub(in super::super) fn sysinfo_ehdr() -> usize {
auxv().sysinfo_ehdr
}
#[inline]
fn auxv() -> &'static Auxv {
unsafe { &AUXV }
}
struct Auxv {
page_size: usize,
clock_ticks_per_second: usize,
hwcap: usize,
hwcap2: usize,
sysinfo_ehdr: usize,
phdr: usize,
phnum: usize,
execfn: usize,
}
static mut AUXV: Auxv = Auxv {
page_size: 0,
clock_ticks_per_second: 0,
hwcap: 0,
hwcap2: 0,
sysinfo_ehdr: 0,
phdr: 0,
phnum: 0,
execfn: 0,
};
#[cfg(all(target_env = "gnu", not(target_vendor = "mustang")))]
#[used]
#[link_section = ".init_array.00099"]
static INIT_ARRAY: unsafe extern "C" fn(c::c_int, *mut *mut u8, *mut *mut u8) = {
unsafe extern "C" fn function(_argc: c::c_int, _argv: *mut *mut u8, envp: *mut *mut u8) {
init_from_envp(envp);
}
function
};
#[cfg(not(any(target_env = "gnu", target_vendor = "mustang")))]
#[used]
#[link_section = ".init_array.00099"]
static INIT_ARRAY: unsafe extern "C" fn() = {
unsafe extern "C" fn function() {
extern "C" {
static __environ: *mut *mut u8;
}
init_from_envp(__environ)
}
function
};
#[cfg(target_vendor = "mustang")]
#[inline]
pub(crate) unsafe fn init(envp: *mut *mut u8) {
init_from_envp(envp);
}
unsafe fn init_from_envp(mut envp: *mut *mut u8) {
while !(*envp).is_null() {
envp = envp.add(1);
}
init_from_auxp(envp.add(1).cast())
}
unsafe fn init_from_auxp(mut auxp: *const Elf_auxv_t) {
loop {
let Elf_auxv_t { a_type, a_val } = *auxp;
match a_type as _ {
AT_PAGESZ => AUXV.page_size = a_val,
AT_CLKTCK => AUXV.clock_ticks_per_second = a_val,
AT_HWCAP => AUXV.hwcap = a_val,
AT_HWCAP2 => AUXV.hwcap2 = a_val,
AT_SYSINFO_EHDR => AUXV.sysinfo_ehdr = a_val,
AT_PHDR => AUXV.phdr = a_val,
AT_PHNUM => AUXV.phnum = a_val,
AT_PHENT => assert_eq!(a_val, size_of::<Elf_Phdr>()),
AT_EXECFN => AUXV.execfn = a_val,
AT_NULL => break,
_ => (),
}
auxp = auxp.add(1);
}
}
#[repr(C)]
#[derive(Copy, Clone)]
struct Elf_auxv_t {
a_type: usize,
a_val: usize,
}