Skip to main content

relibc/header/dl-tls/
mod.rs

1//! dl-tls implementation for Redox
2
3// FIXME(andypython): remove this when #![allow(warnings, unused_variables)] is
4// dropped from src/lib.rs.
5#![warn(warnings, unused_variables)]
6
7#[cfg(target_arch = "x86")]
8use core::arch::global_asm;
9
10use alloc::alloc::alloc;
11use core::{alloc::Layout, ptr};
12
13use crate::{ld_so::tcb::Tcb, platform::types::c_void};
14
15#[repr(C)]
16#[allow(non_camel_case_types)]
17pub struct dl_tls_index {
18    pub ti_module: usize,
19    pub ti_offset: usize,
20}
21
22#[unsafe(no_mangle)]
23pub unsafe extern "C" fn __tls_get_addr(ti: *mut dl_tls_index) -> *mut c_void {
24    let tcb = unsafe { Tcb::current().unwrap() };
25    let ti = unsafe { &*ti };
26    let masters = tcb.masters().unwrap();
27
28    #[cfg(feature = "trace_tls")]
29    log::trace!(
30        "__tls_get_addr({:p}: {:#x}, {:#x}, masters_len={}, dtv_len={})",
31        ti,
32        ti.ti_module,
33        ti.ti_offset,
34        masters.len(),
35        tcb.dtv_mut().len()
36    );
37
38    if tcb.dtv_mut().len() < masters.len() {
39        // Reallocate DTV.
40        tcb.setup_dtv(masters.len());
41    }
42
43    let dtv_index = ti.ti_module - 1;
44
45    if tcb.dtv_mut()[dtv_index].is_null() {
46        // Allocate TLS for module.
47        let master = &masters[dtv_index];
48
49        let module_tls = unsafe {
50            // FIXME(andypython): master.align
51            let layout = Layout::from_size_align_unchecked(master.segment_size, 16);
52            let ptr = alloc(layout);
53
54            ptr::copy_nonoverlapping(master.ptr, ptr, master.image_size);
55            ptr::write_bytes(
56                ptr.add(master.image_size),
57                0,
58                master.segment_size - master.image_size,
59            );
60
61            ptr
62        };
63
64        // Set the DTV entry.
65        tcb.dtv_mut()[dtv_index] = module_tls;
66    }
67
68    let mut ptr = tcb.dtv_mut()[dtv_index];
69
70    if ptr.is_null() {
71        panic!(
72            "__tls_get_addr({ti:p}: {:#x}, {:#x})",
73            ti.ti_module, ti.ti_offset
74        );
75    }
76
77    if cfg!(target_arch = "riscv64") {
78        ptr = unsafe { ptr.add(0x800 + ti.ti_offset) }; // dynamic offsets are 0x800-based on risc-v
79    } else {
80        ptr = unsafe { ptr.add(ti.ti_offset) };
81    }
82
83    ptr.cast::<c_void>()
84}
85
86// x86 can define a version that passes a pointer to dl_tls_index in eax
87#[cfg(target_arch = "x86")]
88global_asm!(
89    "
90    .globl ___tls_get_addr
91    .type ___tls_get_addr, @function
92___tls_get_addr:
93    push ebp
94    mov ebp, esp
95    push eax
96    call __tls_get_addr
97    add esp, 4
98    pop ebp
99    ret
100    .size ___tls_get_addr, . - ___tls_get_addr
101"
102);