123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- use core::{mem, ptr};
- use goblin::elf::program_header::{self, program_header32, program_header64, ProgramHeader};
- use self::tcb::{Master, Tcb};
- use crate::{
- header::sys_auxv::AT_NULL,
- platform::{Pal, Sys},
- start::Stack,
- };
- #[cfg(target_os = "redox")]
- pub const PATH_SEP: char = ';';
- #[cfg(target_os = "linux")]
- pub const PATH_SEP: char = ':';
- mod access;
- pub mod callbacks;
- pub mod debug;
- mod dso;
- pub mod linker;
- pub mod start;
- pub mod tcb;
- static mut STATIC_TCB_MASTER: Master = Master {
- ptr: ptr::null_mut(),
- len: 0,
- offset: 0,
- };
- fn panic_notls(msg: impl core::fmt::Display) -> ! {
- eprintln!("panicked in ld.so: {}", msg);
- unsafe {
- core::intrinsics::abort();
- }
- }
- pub trait ExpectTlsFree {
- type Unwrapped;
- fn expect_notls(self, msg: &str) -> Self::Unwrapped;
- }
- impl<T, E: core::fmt::Debug> ExpectTlsFree for Result<T, E> {
- type Unwrapped = T;
- fn expect_notls(self, msg: &str) -> T {
- match self {
- Ok(t) => t,
- Err(err) => panic_notls(format_args!("expect failed for Result with err: {:?}", err)),
- }
- }
- }
- impl<T> ExpectTlsFree for Option<T> {
- type Unwrapped = T;
- fn expect_notls(self, msg: &str) -> T {
- match self {
- Some(t) => t,
- None => panic_notls("expect failed for Option"),
- }
- }
- }
- #[inline(never)]
- pub fn static_init(sp: &'static Stack) {
- let mut phdr_opt = None;
- let mut phent_opt = None;
- let mut phnum_opt = None;
- let mut auxv = sp.auxv();
- loop {
- let (kind, value) = unsafe { *auxv };
- if kind == AT_NULL {
- break;
- }
- match kind {
- 3 => phdr_opt = Some(value),
- 4 => phent_opt = Some(value),
- 5 => phnum_opt = Some(value),
- _ => (),
- }
- auxv = unsafe { auxv.add(1) };
- }
- let phdr = phdr_opt.expect_notls("failed to find AT_PHDR");
- let phent = phent_opt.expect_notls("failed to find AT_PHENT");
- let phnum = phnum_opt.expect_notls("failed to find AT_PHNUM");
- for i in 0..phnum {
- let ph_addr = phdr + phent * i;
- let ph: ProgramHeader = match phent {
- program_header32::SIZEOF_PHDR => {
- unsafe { *(ph_addr as *const program_header32::ProgramHeader) }.into()
- }
- program_header64::SIZEOF_PHDR => {
- unsafe { *(ph_addr as *const program_header64::ProgramHeader) }.into()
- }
- _ => panic_notls(format_args!("unknown AT_PHENT size {}", phent)),
- };
- let page_size = Sys::getpagesize();
- let voff = ph.p_vaddr as usize % page_size;
- let vaddr = ph.p_vaddr as usize - voff;
- let vsize = ((ph.p_memsz as usize + voff + page_size - 1) / page_size) * page_size;
- match ph.p_type {
- program_header::PT_TLS => {
- let valign = if ph.p_align > 0 {
- ((ph.p_memsz + (ph.p_align - 1)) / ph.p_align) * ph.p_align
- } else {
- ph.p_memsz
- } as usize;
- unsafe {
- STATIC_TCB_MASTER.ptr = ph.p_vaddr as usize as *const u8;
- STATIC_TCB_MASTER.len = ph.p_filesz as usize;
- STATIC_TCB_MASTER.offset = valign;
- let tcb = Tcb::new(vsize).expect_notls("failed to allocate TCB");
- tcb.masters_ptr = &mut STATIC_TCB_MASTER;
- tcb.masters_len = mem::size_of::<Master>();
- tcb.copy_masters().expect_notls("failed to copy TLS master data");
- tcb.activate();
- }
- //TODO: Warning on multiple TLS sections?
- return;
- }
- _ => (),
- }
- }
- }
- #[cfg(any(target_os = "linux", target_os = "redox"))]
- pub unsafe fn init(sp: &'static Stack) {
- let mut tp = 0usize;
- #[cfg(target_os = "linux")]
- {
- const ARCH_GET_FS: usize = 0x1003;
- syscall!(ARCH_PRCTL, ARCH_GET_FS, &mut tp as *mut usize);
- }
- #[cfg(target_os = "redox")]
- {
- let mut env = syscall::EnvRegisters::default();
- let file = syscall::open("thisproc:current/regs/env", syscall::O_CLOEXEC | syscall::O_RDONLY)
- .expect_notls("failed to open handle for process registers");
- let _ = syscall::read(file, &mut env)
- .expect_notls("failed to read fsbase");
- let _ = syscall::close(file);
- tp = env.fsbase as usize;
- }
- if tp == 0 {
- static_init(sp);
- }
- }
- pub unsafe fn fini() {
- if let Some(tcb) = Tcb::current() {
- if tcb.linker_ptr != ptr::null_mut() {
- let linker = (&*tcb.linker_ptr).lock();
- linker.fini();
- }
- }
- }
|