From 1b6a04ca5504955c571d1c97504fb45ea0befee4 Mon Sep 17 00:00:00 2001 From: Valentin Popov Date: Mon, 8 Jan 2024 01:21:28 +0400 Subject: Initial vendor packages Signed-off-by: Valentin Popov --- vendor/rustix/src/backend/linux_raw/runtime/tls.rs | 98 ++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 vendor/rustix/src/backend/linux_raw/runtime/tls.rs (limited to 'vendor/rustix/src/backend/linux_raw/runtime/tls.rs') diff --git a/vendor/rustix/src/backend/linux_raw/runtime/tls.rs b/vendor/rustix/src/backend/linux_raw/runtime/tls.rs new file mode 100644 index 0000000..69bd5ce --- /dev/null +++ b/vendor/rustix/src/backend/linux_raw/runtime/tls.rs @@ -0,0 +1,98 @@ +//! TLS utilities. +//! +//! # Safety +//! +//! This file contains code that reads the raw phdr array pointed to by the +//! kernel-provided AUXV values. +#![allow(unsafe_code)] + +use crate::backend::c; +use crate::backend::param::auxv::exe_phdrs; +use core::arch::global_asm; +use core::ptr::{null, NonNull}; +use linux_raw_sys::elf::*; + +/// 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 (first_phdr, phent, phnum) = exe_phdrs(); + let mut current_phdr = first_phdr.cast::(); + + // The dynamic address of the dynamic section, which we can compare with + // the `PT_DYNAMIC` header's static address, if present. + let dynamic_addr: *const c::c_void = unsafe { &_DYNAMIC }; + + // SAFETY: We assume the phdr array pointer and length the kernel provided + // to the process describe a valid phdr array. + unsafe { + let phdrs_end = current_phdr.cast::().add(phnum * phent).cast(); + while current_phdr != phdrs_end { + let phdr = &*current_phdr; + current_phdr = current_phdr.cast::().add(phent).cast(); + + match phdr.p_type { + // Compute the offset from the static virtual addresses + // in the `p_vaddr` fields to the dynamic addresses. We don't + // always get a `PT_PHDR` or `PT_DYNAMIC` header, so use + // whichever one we get. + PT_PHDR => base = first_phdr.cast::().wrapping_sub(phdr.p_vaddr), + PT_DYNAMIC => base = dynamic_addr.cast::().wrapping_sub(phdr.p_vaddr), + + PT_TLS => tls_phdr = phdr, + PT_GNU_STACK => stack_size = phdr.p_memsz, + _ => {} + } + } + + if tls_phdr.is_null() { + StartupTlsInfo { + addr: NonNull::dangling().as_ptr(), + mem_size: 0, + file_size: 0, + align: 1, + stack_size: 0, + } + } else { + StartupTlsInfo { + addr: base.cast::().wrapping_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, + } + } + } +} + +extern "C" { + /// Declare the `_DYNAMIC` symbol so that we can compare its address with + /// the static address in the `PT_DYNAMIC` header to learn our offset. Use + /// a weak symbol because `_DYNAMIC` is not always present. + static _DYNAMIC: c::c_void; +} +// Rust has `extern_weak` but it isn't stable, so use a `global_asm`. +global_asm!(".weak _DYNAMIC"); + +/// 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, +} -- cgit v1.2.3