tcb.rs 8.3 KB

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