linker.rs 16 KB

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