relibc/header/dl-tls/
mod.rs1#![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 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 let master = &masters[dtv_index];
48
49 let module_tls = unsafe {
50 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 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) }; } else {
80 ptr = unsafe { ptr.add(ti.ti_offset) };
81 }
82
83 ptr.cast::<c_void>()
84}
85
86#[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);