2
0

linker.rs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. use alloc::{
  2. collections::BTreeMap,
  3. rc::Rc,
  4. string::{String, ToString},
  5. vec::Vec,
  6. };
  7. use core::{cell::RefCell, mem::transmute, ptr};
  8. use goblin::{
  9. elf::{program_header, reloc, Elf},
  10. error::{Error, Result},
  11. };
  12. use crate::{
  13. c_str::CString,
  14. fs::File,
  15. header::{fcntl, sys_mman, unistd::F_OK},
  16. io::Read,
  17. platform::types::c_void,
  18. };
  19. use super::{
  20. access::accessible,
  21. callbacks::LinkerCallbacks,
  22. debug::{RTLDState, _dl_debug_state, _r_debug},
  23. dso::{is_pie_enabled, DSO},
  24. tcb::{round_up, Master, Tcb},
  25. PATH_SEP,
  26. };
  27. #[derive(Clone, Copy, Debug)]
  28. pub struct Symbol {
  29. pub value: usize,
  30. pub base: usize,
  31. pub size: usize,
  32. }
  33. impl Symbol {
  34. pub fn as_ptr(self) -> *mut c_void {
  35. (self.base + self.value) as *mut c_void
  36. }
  37. }
  38. pub struct Linker {
  39. ld_library_path: Option<String>,
  40. next_object_id: usize,
  41. next_tls_module_id: usize,
  42. tls_size: usize,
  43. objects: BTreeMap<usize, DSO>,
  44. name_to_object_id_map: BTreeMap<String, usize>,
  45. pub cbs: Rc<RefCell<LinkerCallbacks>>,
  46. }
  47. const root_id: usize = 1;
  48. impl Linker {
  49. pub fn new(ld_library_path: Option<String>) -> Self {
  50. Self {
  51. ld_library_path: ld_library_path,
  52. next_object_id: root_id,
  53. next_tls_module_id: 0,
  54. tls_size: 0,
  55. objects: BTreeMap::new(),
  56. name_to_object_id_map: BTreeMap::new(),
  57. cbs: Rc::new(RefCell::new(LinkerCallbacks::new())),
  58. }
  59. }
  60. pub fn load_program(&mut self, path: &str, base_addr: Option<usize>) -> Result<usize> {
  61. self.load_object(path, &None, base_addr, false)?;
  62. return Ok(self.objects.get(&root_id).unwrap().entry_point);
  63. }
  64. pub fn load_library(&mut self, name: Option<&str>) -> Result<usize> {
  65. match name {
  66. Some(name) => {
  67. if let Some(id) = self.name_to_object_id_map.get(name) {
  68. let obj = self.objects.get_mut(id).unwrap();
  69. obj.use_count += 1;
  70. return Ok(*id);
  71. } else {
  72. let parent_runpath = &self.objects.get(&root_id).unwrap().runpath.clone();
  73. let lib_id = self.next_object_id;
  74. self.load_object(name, parent_runpath, None, true)?;
  75. return Ok(lib_id);
  76. }
  77. }
  78. None => return Ok(root_id),
  79. }
  80. }
  81. pub fn get_sym(&self, lib_id: usize, name: &str) -> Option<*mut c_void> {
  82. match self.objects.get(&lib_id) {
  83. Some(obj) => obj.get_sym(name).map(|s| s.as_ptr()),
  84. _ => None,
  85. }
  86. }
  87. pub fn unload(&mut self, lib_id: usize) {
  88. if let Some(obj) = self.objects.get_mut(&lib_id) {
  89. if obj.dlopened {
  90. if obj.use_count == 1 {
  91. let obj = self.objects.remove(&lib_id).unwrap();
  92. for dep in obj.dependencies.iter() {
  93. self.unload(*self.name_to_object_id_map.get(dep).unwrap());
  94. }
  95. self.name_to_object_id_map.remove(&obj.name);
  96. drop(obj);
  97. } else {
  98. obj.use_count -= 1;
  99. }
  100. }
  101. }
  102. }
  103. pub fn fini(&self) {
  104. for obj in self.objects.values() {
  105. obj.run_fini();
  106. }
  107. }
  108. fn load_object(
  109. &mut self,
  110. path: &str,
  111. runpath: &Option<String>,
  112. base_addr: Option<usize>,
  113. dlopened: bool,
  114. ) -> Result<()> {
  115. unsafe { _r_debug.state = RTLDState::RT_ADD };
  116. _dl_debug_state();
  117. let mut new_objects = Vec::new();
  118. let mut objects_data = Vec::new();
  119. let mut tcb_masters = Vec::new();
  120. self.load_objects_recursive(
  121. path,
  122. runpath,
  123. base_addr,
  124. dlopened,
  125. &mut new_objects,
  126. &mut objects_data,
  127. &mut tcb_masters,
  128. )?;
  129. unsafe {
  130. let tcb = if self.objects.len() == 0 {
  131. Tcb::new(self.tls_size)?
  132. } else {
  133. Tcb::current().unwrap()
  134. };
  135. tcb.append_masters(tcb_masters);
  136. tcb.copy_masters()?;
  137. tcb.activate();
  138. }
  139. self.relocate(&new_objects, &objects_data)?;
  140. self.run_init(&new_objects);
  141. for obj in new_objects.into_iter() {
  142. self.name_to_object_id_map.insert(obj.name.clone(), obj.id);
  143. self.objects.insert(obj.id, obj);
  144. }
  145. unsafe { _r_debug.state = RTLDState::RT_CONSISTENT };
  146. _dl_debug_state();
  147. return Ok(());
  148. }
  149. fn load_objects_recursive(
  150. &mut self,
  151. name: &str,
  152. parent_runpath: &Option<String>,
  153. base_addr: Option<usize>,
  154. dlopened: bool,
  155. new_objects: &mut Vec<DSO>,
  156. objects_data: &mut Vec<Vec<u8>>,
  157. tcb_masters: &mut Vec<Master>,
  158. ) -> Result<()> {
  159. if let Some(obj) = {
  160. if let Some(id) = self.name_to_object_id_map.get(name) {
  161. self.objects.get_mut(id)
  162. } else {
  163. new_objects.iter_mut().find(|o| o.name == name)
  164. }
  165. } {
  166. obj.use_count += 1;
  167. return Ok(());
  168. }
  169. let path = Linker::search_object(name, &self.ld_library_path, parent_runpath)?;
  170. let data = Linker::read_file(&path)?;
  171. let (obj, tcb_master) = DSO::new(
  172. &path,
  173. &data,
  174. base_addr,
  175. dlopened,
  176. self.next_object_id,
  177. self.next_tls_module_id,
  178. self.tls_size,
  179. )?;
  180. new_objects.push(obj);
  181. objects_data.push(data);
  182. self.next_object_id += 1;
  183. if let Some(master) = tcb_master {
  184. self.next_tls_module_id += 1;
  185. self.tls_size = master.offset;
  186. tcb_masters.push(master);
  187. }
  188. let (runpath, dependencies) = {
  189. let parent = new_objects.last().unwrap();
  190. (parent.runpath.clone(), parent.dependencies.clone())
  191. };
  192. for dep_name in dependencies.iter() {
  193. self.load_objects_recursive(
  194. dep_name,
  195. &runpath,
  196. None,
  197. dlopened,
  198. new_objects,
  199. objects_data,
  200. tcb_masters,
  201. )?;
  202. }
  203. return Ok(());
  204. }
  205. fn search_object(
  206. name: &str,
  207. ld_library_path: &Option<String>,
  208. parent_runpath: &Option<String>,
  209. ) -> Result<String> {
  210. let mut full_path = name.to_string();
  211. if accessible(&full_path, F_OK) == 0 {
  212. return Ok(full_path);
  213. } else {
  214. let mut search_paths = Vec::new();
  215. if let Some(runpath) = parent_runpath {
  216. search_paths.extend(runpath.split(PATH_SEP));
  217. }
  218. if let Some(ld_path) = ld_library_path {
  219. search_paths.extend(ld_path.split(PATH_SEP));
  220. }
  221. search_paths.push("/lib");
  222. for part in search_paths.iter() {
  223. full_path = format!("{}/{}", part, name);
  224. trace!("trying path {}", full_path);
  225. if accessible(&full_path, F_OK) == 0 {
  226. return Ok(full_path);
  227. }
  228. }
  229. }
  230. return Err(Error::Malformed(format!("failed to locate '{}'", name)));
  231. }
  232. fn read_file(path: &str) -> Result<Vec<u8>> {
  233. let mut data = Vec::new();
  234. let path_c = CString::new(path)
  235. .map_err(|err| Error::Malformed(format!("invalid path '{}': {}", path, err)))?;
  236. let flags = fcntl::O_RDONLY | fcntl::O_CLOEXEC;
  237. let mut file = File::open(&path_c, flags)
  238. .map_err(|err| Error::Malformed(format!("failed to open '{}': {}", path, err)))?;
  239. file.read_to_end(&mut data)
  240. .map_err(|err| Error::Malformed(format!("failed to read '{}': {}", path, err)))?;
  241. return Ok(data);
  242. }
  243. fn relocate(&self, new_objects: &Vec<DSO>, objects_data: &Vec<Vec<u8>>) -> Result<()> {
  244. let symbols_lookup_objects: Vec<&DSO> =
  245. self.objects.values().chain(new_objects.iter()).collect();
  246. // Perform relocations
  247. for i in (0..new_objects.len()).rev() {
  248. let elf = Elf::parse(&objects_data[i])?;
  249. let obj = &new_objects[i];
  250. trace!("link {}", obj.name);
  251. let mmap = &obj.mmap;
  252. let b = mmap.as_ptr() as usize;
  253. // Relocate
  254. for rel in elf
  255. .dynrelas
  256. .iter()
  257. .chain(elf.dynrels.iter())
  258. .chain(elf.pltrelocs.iter())
  259. {
  260. trace!(
  261. " rel {}: {:x?}",
  262. reloc::r_to_str(rel.r_type, elf.header.e_machine),
  263. rel
  264. );
  265. let (symbol, t) = if rel.r_sym > 0 {
  266. let sym = elf.dynsyms.get(rel.r_sym).ok_or(Error::Malformed(format!(
  267. "missing symbol for relocation {:?}",
  268. rel
  269. )))?;
  270. let mut t = 0;
  271. let name =
  272. elf.dynstrtab
  273. .get(sym.st_name)
  274. .ok_or(Error::Malformed(format!(
  275. "missing name for symbol {:?}",
  276. sym
  277. )))??;
  278. let mut symbol = None;
  279. let mut found = false;
  280. let lookup_start = match rel.r_type {
  281. reloc::R_X86_64_COPY => 1,
  282. _ => 0,
  283. };
  284. for lookup_id in lookup_start..symbols_lookup_objects.len() {
  285. let obj = &symbols_lookup_objects[lookup_id];
  286. let s = obj.get_sym(name);
  287. if s.is_some() {
  288. trace!("symbol {} from {} found in {}", name, obj.name, obj.name);
  289. symbol = s;
  290. t = obj.tls_offset;
  291. found = true;
  292. break;
  293. }
  294. }
  295. // TODO: below doesn't work because of missing __preinit_array_{start,end} and __init_array_{start,end} symbols in dynamic linked programs
  296. /*
  297. if !found {
  298. return Err(Error::Malformed(format!("missing symbol for name {}", name)));
  299. }
  300. */
  301. (symbol, t)
  302. } else {
  303. (None, 0)
  304. };
  305. let s = symbol
  306. .as_ref()
  307. .map(|sym| sym.as_ptr() as usize)
  308. .unwrap_or(0);
  309. let a = rel.r_addend.unwrap_or(0) as usize;
  310. let ptr = if is_pie_enabled(&elf) {
  311. (b + rel.r_offset as usize) as *mut u8
  312. } else {
  313. rel.r_offset as *mut u8
  314. };
  315. let set_u64 = |value| {
  316. trace!(" set_u64 {:#x}", value);
  317. unsafe {
  318. *(ptr as *mut u64) = value;
  319. }
  320. };
  321. match rel.r_type {
  322. reloc::R_X86_64_64 => {
  323. set_u64((s + a) as u64);
  324. }
  325. reloc::R_X86_64_DTPMOD64 => {
  326. set_u64(obj.tls_module_id as u64);
  327. }
  328. reloc::R_X86_64_DTPOFF64 => {
  329. if s != 0 {
  330. set_u64((s - b) as u64);
  331. } else {
  332. set_u64(s as u64);
  333. }
  334. }
  335. reloc::R_X86_64_GLOB_DAT | reloc::R_X86_64_JUMP_SLOT => {
  336. set_u64(s as u64);
  337. }
  338. reloc::R_X86_64_RELATIVE => {
  339. set_u64((b + a) as u64);
  340. }
  341. reloc::R_X86_64_TPOFF64 => {
  342. let sym = symbol
  343. .as_ref()
  344. .expect("R_X86_64_TPOFF64 called without valid symbol");
  345. set_u64((sym.value + a).wrapping_sub(t) as u64);
  346. }
  347. reloc::R_X86_64_IRELATIVE => unsafe {
  348. let f: unsafe extern "C" fn() -> u64 = transmute(b + a);
  349. set_u64(f());
  350. },
  351. reloc::R_X86_64_COPY => unsafe {
  352. let sym = symbol
  353. .as_ref()
  354. .expect("R_X86_64_COPY called without valid symbol");
  355. ptr::copy_nonoverlapping(sym.as_ptr() as *const u8, ptr, sym.size as usize);
  356. },
  357. _ => {
  358. panic!(
  359. " {} unsupported",
  360. reloc::r_to_str(rel.r_type, elf.header.e_machine)
  361. );
  362. }
  363. }
  364. }
  365. // Protect pages
  366. for ph in elf
  367. .program_headers
  368. .iter()
  369. .filter(|ph| ph.p_type == program_header::PT_LOAD)
  370. {
  371. let voff = ph.p_vaddr % ph.p_align;
  372. let vaddr = (ph.p_vaddr - voff) as usize;
  373. let vsize = round_up((ph.p_memsz + voff) as usize, ph.p_align as usize);
  374. let mut prot = 0;
  375. if ph.p_flags & program_header::PF_R == program_header::PF_R {
  376. prot |= sys_mman::PROT_READ;
  377. }
  378. // W ^ X. If it is executable, do not allow it to be writable, even if requested
  379. if ph.p_flags & program_header::PF_X == program_header::PF_X {
  380. prot |= sys_mman::PROT_EXEC;
  381. } else if ph.p_flags & program_header::PF_W == program_header::PF_W {
  382. prot |= sys_mman::PROT_WRITE;
  383. }
  384. let res = unsafe {
  385. let ptr = if is_pie_enabled(&elf) {
  386. mmap.as_ptr().add(vaddr)
  387. } else {
  388. vaddr as *const u8
  389. };
  390. trace!(" prot {:#x}, {:#x}: {:p}, {:#x}", vaddr, vsize, ptr, prot);
  391. sys_mman::mprotect(ptr as *mut c_void, vsize, prot)
  392. };
  393. if res < 0 {
  394. return Err(Error::Malformed(format!("failed to mprotect {}", obj.name)));
  395. }
  396. }
  397. }
  398. return Ok(());
  399. }
  400. fn run_init(&self, objects: &Vec<DSO>) {
  401. for obj in objects.iter().rev() {
  402. obj.run_init();
  403. }
  404. }
  405. }