1 use core::{mem, ptr}; 2 use goblin::elf::program_header::{self, program_header32, program_header64, ProgramHeader}; 3 4 use self::tcb::{Master, Tcb}; 5 use crate::{header::sys_auxv::AT_NULL, start::Stack}; 6 7 pub const PAGE_SIZE: usize = 4096; 8 9 #[cfg(target_os = "redox")] 10 pub const PATH_SEP: char = ';'; 11 12 #[cfg(target_os = "linux")] 13 pub const PATH_SEP: char = ':'; 14 15 mod access; 16 pub mod callbacks; 17 pub mod debug; 18 mod dso; 19 pub mod linker; 20 pub mod start; 21 pub mod tcb; 22 23 static mut STATIC_TCB_MASTER: Master = Master { 24 ptr: ptr::null_mut(), 25 len: 0, 26 offset: 0, 27 }; 28 29 pub fn static_init(sp: &'static Stack) { 30 let mut phdr_opt = None; 31 let mut phent_opt = None; 32 let mut phnum_opt = None; 33 34 let mut auxv = sp.auxv(); 35 loop { 36 let (kind, value) = unsafe { *auxv }; 37 if kind == AT_NULL { 38 break; 39 } 40 41 match kind { 42 3 => phdr_opt = Some(value), 43 4 => phent_opt = Some(value), 44 5 => phnum_opt = Some(value), 45 _ => (), 46 } 47 48 auxv = unsafe { auxv.add(1) }; 49 } 50 51 let phdr = phdr_opt.expect("failed to find AT_PHDR"); 52 let phent = phent_opt.expect("failed to find AT_PHENT"); 53 let phnum = phnum_opt.expect("failed to find AT_PHNUM"); 54 55 for i in 0..phnum { 56 let ph_addr = phdr + phent * i; 57 let ph: ProgramHeader = match phent { 58 program_header32::SIZEOF_PHDR => { 59 unsafe { *(ph_addr as *const program_header32::ProgramHeader) }.into() 60 } 61 program_header64::SIZEOF_PHDR => { 62 unsafe { *(ph_addr as *const program_header64::ProgramHeader) }.into() 63 } 64 _ => panic!("unknown AT_PHENT size {}", phent), 65 }; 66 67 let voff = ph.p_vaddr as usize % PAGE_SIZE; 68 let vaddr = ph.p_vaddr as usize - voff; 69 let vsize = ((ph.p_memsz as usize + voff + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE; 70 71 match ph.p_type { 72 program_header::PT_TLS => { 73 let valign = if ph.p_align > 0 { 74 ((ph.p_memsz + (ph.p_align - 1)) / ph.p_align) * ph.p_align 75 } else { 76 ph.p_memsz 77 } as usize; 78 79 unsafe { 80 STATIC_TCB_MASTER.ptr = ph.p_vaddr as usize as *const u8; 81 STATIC_TCB_MASTER.len = ph.p_filesz as usize; 82 STATIC_TCB_MASTER.offset = valign; 83 84 let tcb = Tcb::new(vsize).expect("failed to allocate TCB"); 85 tcb.masters_ptr = &mut STATIC_TCB_MASTER; 86 tcb.masters_len = mem::size_of::<Master>(); 87 tcb.copy_masters().expect("failed to copy TLS master data"); 88 tcb.activate(); 89 } 90 91 //TODO: Warning on multiple TLS sections? 92 return; 93 } 94 _ => (), 95 } 96 } 97 } 98 99 #[cfg(target_os = "linux")] 100 pub unsafe fn init(sp: &'static Stack) { 101 let mut tp = 0usize; 102 const ARCH_GET_FS: usize = 0x1003; 103 syscall!(ARCH_PRCTL, ARCH_GET_FS, &mut tp as *mut usize); 104 if tp == 0 { 105 static_init(sp); 106 } 107 } 108 109 #[cfg(target_os = "redox")] 110 pub unsafe fn init(_sp: &'static Stack) {} 111 112 pub unsafe fn fini() { 113 if let Some(tcb) = Tcb::current() { 114 if tcb.linker_ptr != ptr::null_mut() { 115 let linker = (&*tcb.linker_ptr).lock(); 116 linker.fini(); 117 } 118 } 119 } 120