#![allow(unsafe_code)] use super::super::c; use super::super::elf::*; use super::super::param::auxv::exe_phdrs_slice; use core::ptr::null; /// For use with [`set_thread_area`]. /// /// [`set_thread_area`]: crate::runtime::set_thread_area #[cfg(target_arch = "x86")] pub type UserDesc = linux_raw_sys::general::user_desc; pub(crate) fn startup_tls_info() -> StartupTlsInfo { let mut base = null(); let mut tls_phdr = null(); let mut stack_size = 0; let phdrs = exe_phdrs_slice(); // Safety: We assume the phdr array pointer and length the kernel provided // to the process describe a valid phdr array. unsafe { for phdr in phdrs { match (*phdr).p_type { PT_PHDR => { base = phdrs .as_ptr() .cast::() .offset(-((*phdr).p_vaddr as isize)) } PT_TLS => tls_phdr = phdr, PT_GNU_STACK => stack_size = (*phdr).p_memsz, _ => {} } } StartupTlsInfo { addr: base.cast::().add((*tls_phdr).p_vaddr).cast(), mem_size: (*tls_phdr).p_memsz, file_size: (*tls_phdr).p_filesz, align: (*tls_phdr).p_align, stack_size, } } } /// The values returned from [`startup_tls_info`]. /// /// [`startup_tls_info`]: crate::runtime::startup_tls_info pub struct StartupTlsInfo { /// The base address of the TLS segment. pub addr: *const c::c_void, /// The size of the memory region. pub mem_size: usize, /// The size beyond which all memory is zero-initialized. pub file_size: usize, /// The required alignment for the TLS segment. pub align: usize, /// The requested minimum size for stacks. pub stack_size: usize, }