mod.rs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. use core::{mem, ptr};
  2. use goblin::elf::program_header::{self, program_header32, program_header64, ProgramHeader};
  3. use self::tcb::{Master, Tcb};
  4. use crate::{
  5. header::sys_auxv::AT_NULL,
  6. platform::{Pal, Sys},
  7. start::Stack,
  8. };
  9. #[cfg(target_os = "redox")]
  10. pub const PATH_SEP: char = ';';
  11. #[cfg(target_os = "linux")]
  12. pub const PATH_SEP: char = ':';
  13. mod access;
  14. pub mod callbacks;
  15. pub mod debug;
  16. mod dso;
  17. pub mod linker;
  18. pub mod start;
  19. pub mod tcb;
  20. static mut STATIC_TCB_MASTER: Master = Master {
  21. ptr: ptr::null_mut(),
  22. len: 0,
  23. offset: 0,
  24. };
  25. fn panic_notls(msg: impl core::fmt::Display) -> ! {
  26. eprintln!("panicked in ld.so: {}", msg);
  27. unsafe {
  28. core::intrinsics::abort();
  29. }
  30. }
  31. pub trait ExpectTlsFree {
  32. type Unwrapped;
  33. fn expect_notls(self, msg: &str) -> Self::Unwrapped;
  34. }
  35. impl<T, E: core::fmt::Debug> ExpectTlsFree for Result<T, E> {
  36. type Unwrapped = T;
  37. fn expect_notls(self, msg: &str) -> T {
  38. match self {
  39. Ok(t) => t,
  40. Err(err) => panic_notls(format_args!("expect failed for Result with err: {:?}", err)),
  41. }
  42. }
  43. }
  44. impl<T> ExpectTlsFree for Option<T> {
  45. type Unwrapped = T;
  46. fn expect_notls(self, msg: &str) -> T {
  47. match self {
  48. Some(t) => t,
  49. None => panic_notls("expect failed for Option"),
  50. }
  51. }
  52. }
  53. #[inline(never)]
  54. pub fn static_init(sp: &'static Stack) {
  55. let mut phdr_opt = None;
  56. let mut phent_opt = None;
  57. let mut phnum_opt = None;
  58. let mut auxv = sp.auxv();
  59. loop {
  60. let (kind, value) = unsafe { *auxv };
  61. if kind == AT_NULL {
  62. break;
  63. }
  64. match kind {
  65. 3 => phdr_opt = Some(value),
  66. 4 => phent_opt = Some(value),
  67. 5 => phnum_opt = Some(value),
  68. _ => (),
  69. }
  70. auxv = unsafe { auxv.add(1) };
  71. }
  72. let phdr = phdr_opt.expect_notls("failed to find AT_PHDR");
  73. let phent = phent_opt.expect_notls("failed to find AT_PHENT");
  74. let phnum = phnum_opt.expect_notls("failed to find AT_PHNUM");
  75. for i in 0..phnum {
  76. let ph_addr = phdr + phent * i;
  77. let ph: ProgramHeader = match phent {
  78. program_header32::SIZEOF_PHDR => {
  79. unsafe { *(ph_addr as *const program_header32::ProgramHeader) }.into()
  80. }
  81. program_header64::SIZEOF_PHDR => {
  82. unsafe { *(ph_addr as *const program_header64::ProgramHeader) }.into()
  83. }
  84. _ => panic_notls(format_args!("unknown AT_PHENT size {}", phent)),
  85. };
  86. let page_size = Sys::getpagesize();
  87. let voff = ph.p_vaddr as usize % page_size;
  88. let vaddr = ph.p_vaddr as usize - voff;
  89. let vsize = ((ph.p_memsz as usize + voff + page_size - 1) / page_size) * page_size;
  90. match ph.p_type {
  91. program_header::PT_TLS => {
  92. let valign = if ph.p_align > 0 {
  93. ((ph.p_memsz + (ph.p_align - 1)) / ph.p_align) * ph.p_align
  94. } else {
  95. ph.p_memsz
  96. } as usize;
  97. unsafe {
  98. STATIC_TCB_MASTER.ptr = ph.p_vaddr as usize as *const u8;
  99. STATIC_TCB_MASTER.len = ph.p_filesz as usize;
  100. STATIC_TCB_MASTER.offset = valign;
  101. let tcb = Tcb::new(vsize).expect_notls("failed to allocate TCB");
  102. tcb.masters_ptr = &mut STATIC_TCB_MASTER;
  103. tcb.masters_len = mem::size_of::<Master>();
  104. tcb.copy_masters().expect_notls("failed to copy TLS master data");
  105. tcb.activate();
  106. }
  107. //TODO: Warning on multiple TLS sections?
  108. return;
  109. }
  110. _ => (),
  111. }
  112. }
  113. }
  114. #[cfg(any(target_os = "linux", target_os = "redox"))]
  115. pub unsafe fn init(sp: &'static Stack) {
  116. let mut tp = 0usize;
  117. #[cfg(target_os = "linux")]
  118. {
  119. const ARCH_GET_FS: usize = 0x1003;
  120. syscall!(ARCH_PRCTL, ARCH_GET_FS, &mut tp as *mut usize);
  121. }
  122. #[cfg(target_os = "redox")]
  123. {
  124. let mut env = syscall::EnvRegisters::default();
  125. let file = syscall::open("thisproc:current/regs/env", syscall::O_CLOEXEC | syscall::O_RDONLY)
  126. .expect_notls("failed to open handle for process registers");
  127. let _ = syscall::read(file, &mut env)
  128. .expect_notls("failed to read fsbase");
  129. let _ = syscall::close(file);
  130. tp = env.fsbase as usize;
  131. }
  132. if tp == 0 {
  133. static_init(sp);
  134. }
  135. }
  136. pub unsafe fn fini() {
  137. if let Some(tcb) = Tcb::current() {
  138. if tcb.linker_ptr != ptr::null_mut() {
  139. let linker = (&*tcb.linker_ptr).lock();
  140. linker.fini();
  141. }
  142. }
  143. }