tcb.rs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. use core::{mem, ptr, slice};
  2. use core::arch::asm;
  3. use alloc::vec::Vec;
  4. use goblin::error::{Error, Result};
  5. use crate::{
  6. header::sys_mman,
  7. ld_so::{linker::Linker, ExpectTlsFree},
  8. platform::{Pal, Sys},
  9. sync::mutex::Mutex,
  10. };
  11. #[repr(C)]
  12. #[derive(Debug)]
  13. pub struct Master {
  14. /// Pointer to initial data
  15. pub ptr: *const u8,
  16. /// Length of initial data in bytes
  17. pub len: usize,
  18. /// Offset in TLS to copy initial data to
  19. pub offset: usize,
  20. }
  21. impl Master {
  22. /// The initial data for this TLS region
  23. pub unsafe fn data(&self) -> &'static [u8] {
  24. slice::from_raw_parts(self.ptr, self.len)
  25. }
  26. }
  27. #[derive(Debug)]
  28. #[repr(C)]
  29. pub struct Tcb {
  30. /// Pointer to the end of static TLS. Must be the first member
  31. pub tls_end: *mut u8,
  32. /// Size of the memory allocated for the static TLS in bytes (multiple of page size)
  33. pub tls_len: usize,
  34. /// Pointer to this structure
  35. pub tcb_ptr: *mut Tcb,
  36. /// Size of the memory allocated for this structure in bytes (should be same as page size)
  37. pub tcb_len: usize,
  38. /// Pointer to a list of initial TLS data
  39. pub masters_ptr: *mut Master,
  40. /// Size of the masters list in bytes (multiple of mem::size_of::<Master>())
  41. pub masters_len: usize,
  42. /// Index of last copied Master
  43. pub num_copied_masters: usize,
  44. /// Pointer to dynamic linker
  45. pub linker_ptr: *const Mutex<Linker>,
  46. /// pointer to rust memory allocator structure
  47. pub mspace: usize,
  48. }
  49. impl Tcb {
  50. /// Create a new TCB
  51. pub unsafe fn new(size: usize) -> Result<&'static mut Self> {
  52. let page_size = Sys::getpagesize();
  53. let (tls, tcb_page) = Self::os_new(round_up(size, page_size))?;
  54. let tcb_ptr = tcb_page.as_mut_ptr() as *mut Self;
  55. trace!("New TCB: {:p}", tcb_ptr);
  56. ptr::write(
  57. tcb_ptr,
  58. Self {
  59. tls_end: tls.as_mut_ptr().add(tls.len()),
  60. tls_len: tls.len(),
  61. tcb_ptr,
  62. tcb_len: tcb_page.len(),
  63. masters_ptr: ptr::null_mut(),
  64. masters_len: 0,
  65. num_copied_masters: 0,
  66. linker_ptr: ptr::null(),
  67. mspace: 0,
  68. },
  69. );
  70. Ok(&mut *tcb_ptr)
  71. }
  72. /// Get the current TCB
  73. pub unsafe fn current() -> Option<&'static mut Self> {
  74. let tcb_ptr = Self::arch_read(offset_of!(Self, tcb_ptr)) as *mut Self;
  75. let tcb_len = Self::arch_read(offset_of!(Self, tcb_len));
  76. if tcb_ptr.is_null() || tcb_len < mem::size_of::<Self>() {
  77. None
  78. } else {
  79. Some(&mut *tcb_ptr)
  80. }
  81. }
  82. /// A slice for all of the TLS data
  83. pub unsafe fn tls(&self) -> Option<&'static mut [u8]> {
  84. if self.tls_end.is_null() || self.tls_len == 0 {
  85. None
  86. } else {
  87. Some(slice::from_raw_parts_mut(
  88. self.tls_end.offset(-(self.tls_len as isize)),
  89. self.tls_len,
  90. ))
  91. }
  92. }
  93. /// The initial images for TLS
  94. pub unsafe fn masters(&self) -> Option<&'static mut [Master]> {
  95. if self.masters_ptr.is_null() || self.masters_len == 0 {
  96. None
  97. } else {
  98. Some(slice::from_raw_parts_mut(
  99. self.masters_ptr,
  100. self.masters_len / mem::size_of::<Master>(),
  101. ))
  102. }
  103. }
  104. /// Copy data from masters
  105. pub unsafe fn copy_masters(&mut self) -> Result<()> {
  106. //TODO: Complain if masters or tls exist without the other
  107. if let Some(tls) = self.tls() {
  108. if let Some(masters) = self.masters() {
  109. for (i, master) in masters
  110. .iter()
  111. .skip(self.num_copied_masters)
  112. .filter(|m| m.len > 0)
  113. .enumerate()
  114. {
  115. let range =
  116. self.tls_len - master.offset..self.tls_len - master.offset + master.len;
  117. if let Some(tls_data) = tls.get_mut(range) {
  118. let data = master.data();
  119. trace!(
  120. "tls master {}: {:p}, {:#x}: {:p}, {:#x}",
  121. i,
  122. data.as_ptr(),
  123. data.len(),
  124. tls_data.as_mut_ptr(),
  125. tls_data.len()
  126. );
  127. tls_data.copy_from_slice(data);
  128. } else {
  129. return Err(Error::Malformed(format!("failed to copy tls master {}", i)));
  130. }
  131. }
  132. self.num_copied_masters = masters.len();
  133. }
  134. }
  135. Ok(())
  136. }
  137. /// The initial images for TLS
  138. pub unsafe fn append_masters(&mut self, mut new_masters: Vec<Master>) {
  139. if self.masters_ptr.is_null() {
  140. self.masters_ptr = new_masters.as_mut_ptr();
  141. self.masters_len = new_masters.len() * mem::size_of::<Master>();
  142. mem::forget(new_masters);
  143. } else {
  144. let len = self.masters_len / mem::size_of::<Master>();
  145. let mut masters = Vec::from_raw_parts(self.masters_ptr, len, len);
  146. masters.extend(new_masters.into_iter());
  147. self.masters_ptr = masters.as_mut_ptr();
  148. self.masters_len = masters.len() * mem::size_of::<Master>();
  149. mem::forget(masters);
  150. }
  151. }
  152. /// Activate TLS
  153. pub unsafe fn activate(&mut self) {
  154. Self::os_arch_activate(self.tcb_ptr as usize);
  155. }
  156. /// Mapping with correct flags for TCB and TLS
  157. unsafe fn map(size: usize) -> Result<&'static mut [u8]> {
  158. let ptr = sys_mman::mmap(
  159. ptr::null_mut(),
  160. size,
  161. sys_mman::PROT_READ | sys_mman::PROT_WRITE,
  162. sys_mman::MAP_ANONYMOUS | sys_mman::MAP_PRIVATE,
  163. -1,
  164. 0,
  165. );
  166. if ptr as usize == !0
  167. /* MAP_FAILED */
  168. {
  169. return Err(Error::Malformed(format!("failed to map tls")));
  170. }
  171. ptr::write_bytes(ptr as *mut u8, 0, size);
  172. Ok(slice::from_raw_parts_mut(ptr as *mut u8, size))
  173. }
  174. /// OS specific code to create a new TLS and TCB - Linux and Redox
  175. #[cfg(any(target_os = "linux", target_os = "redox"))]
  176. unsafe fn os_new(size: usize) -> Result<(&'static mut [u8], &'static mut [u8])> {
  177. let page_size = Sys::getpagesize();
  178. let tls_tcb = Self::map(size + page_size)?;
  179. Ok(tls_tcb.split_at_mut(size))
  180. }
  181. /// Architecture specific code to read a usize from the TCB - x86_64
  182. #[inline(always)]
  183. #[cfg(target_arch = "aarch64")]
  184. unsafe fn arch_read(offset: usize) -> usize {
  185. // TODO: s/llvm_asm/asm/g
  186. let tp: usize;
  187. asm!(
  188. "mrs {}, tpidr_el0",
  189. out(reg) tp,
  190. );
  191. *((tp + offset) as *const usize)
  192. }
  193. /// Architecture specific code to read a usize from the TCB - x86_64
  194. #[inline(always)]
  195. #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
  196. unsafe fn arch_read(offset: usize) -> usize {
  197. let value;
  198. asm!(
  199. "
  200. mov {}, fs:[{}]
  201. ",
  202. out(reg) value,
  203. in(reg) offset,
  204. );
  205. value
  206. }
  207. /// OS and architecture specific code to activate TLS - Linux x86_64
  208. #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
  209. unsafe fn os_arch_activate(tp: usize) {
  210. const ARCH_SET_FS: usize = 0x1002;
  211. syscall!(ARCH_PRCTL, ARCH_SET_FS, tp);
  212. }
  213. /// OS and architecture specific code to activate TLS - Redox aarch64
  214. #[cfg(all(target_os = "redox", target_arch = "aarch64"))]
  215. unsafe fn os_arch_activate(tp: usize) {
  216. //TODO: aarch64
  217. }
  218. /// OS and architecture specific code to activate TLS - Redox x86
  219. #[cfg(all(target_os = "redox", target_arch = "x86"))]
  220. unsafe fn os_arch_activate(tp: usize) {
  221. let mut env = syscall::EnvRegisters::default();
  222. let file = syscall::open("thisproc:current/regs/env", syscall::O_CLOEXEC | syscall::O_RDWR)
  223. .expect_notls("failed to open handle for process registers");
  224. let _ = syscall::read(file, &mut env)
  225. .expect_notls("failed to read fsbase");
  226. env.fsbase = tp as u32;
  227. let _ = syscall::write(file, &env)
  228. .expect_notls("failed to write fsbase");
  229. let _ = syscall::close(file);
  230. }
  231. /// OS and architecture specific code to activate TLS - Redox x86_64
  232. #[cfg(all(target_os = "redox", target_arch = "x86_64"))]
  233. unsafe fn os_arch_activate(tp: usize) {
  234. let mut env = syscall::EnvRegisters::default();
  235. let file = syscall::open("thisproc:current/regs/env", syscall::O_CLOEXEC | syscall::O_RDWR)
  236. .expect_notls("failed to open handle for process registers");
  237. let _ = syscall::read(file, &mut env)
  238. .expect_notls("failed to read fsbase");
  239. env.fsbase = tp as u64;
  240. let _ = syscall::write(file, &env)
  241. .expect_notls("failed to write fsbase");
  242. let _ = syscall::close(file);
  243. }
  244. }
  245. pub fn round_up(value: usize, alignment: usize) -> usize {
  246. return (value + alignment - 1) & (!(alignment - 1));
  247. }