aboutsummaryrefslogtreecommitdiff
path: root/vendor/rustix/src/backend/linux_raw/runtime/tls.rs
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2024-01-08 00:21:28 +0300
committerValentin Popov <valentin@popov.link>2024-01-08 00:21:28 +0300
commit1b6a04ca5504955c571d1c97504fb45ea0befee4 (patch)
tree7579f518b23313e8a9748a88ab6173d5e030b227 /vendor/rustix/src/backend/linux_raw/runtime/tls.rs
parent5ecd8cf2cba827454317368b68571df0d13d7842 (diff)
downloadfparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.tar.xz
fparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.zip
Initial vendor packages
Signed-off-by: Valentin Popov <valentin@popov.link>
Diffstat (limited to 'vendor/rustix/src/backend/linux_raw/runtime/tls.rs')
-rw-r--r--vendor/rustix/src/backend/linux_raw/runtime/tls.rs98
1 files changed, 98 insertions, 0 deletions
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::<Elf_Phdr>();
+
+ // 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::<u8>().add(phnum * phent).cast();
+ while current_phdr != phdrs_end {
+ let phdr = &*current_phdr;
+ current_phdr = current_phdr.cast::<u8>().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::<u8>().wrapping_sub(phdr.p_vaddr),
+ PT_DYNAMIC => base = dynamic_addr.cast::<u8>().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::<u8>().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,
+}