linker.rs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. use alloc::{
  2. boxed::Box,
  3. collections::BTreeMap,
  4. string::{String, ToString},
  5. vec::Vec,
  6. };
  7. use core::{mem, ptr, slice};
  8. use goblin::{
  9. elf::{program_header, reloc, sym, Elf},
  10. error::{Error, Result},
  11. };
  12. use crate::{
  13. c_str::CString,
  14. fs::File,
  15. header::{fcntl, sys_mman, unistd},
  16. io::Read,
  17. platform::types::c_void,
  18. };
  19. use super::{
  20. tcb::{Master, Tcb},
  21. PAGE_SIZE,
  22. };
  23. #[cfg(target_os = "redox")]
  24. const PATH_SEP: char = ';';
  25. #[cfg(target_os = "linux")]
  26. const PATH_SEP: char = ':';
  27. pub struct Linker {
  28. // Used by load
  29. /// Library path to search when loading library by name
  30. library_path: String,
  31. /// Loaded library raw data
  32. objects: BTreeMap<String, Box<[u8]>>,
  33. // Used by link
  34. /// Global symbols
  35. globals: BTreeMap<String, usize>,
  36. /// Weak symbols
  37. weak_syms: BTreeMap<String, usize>,
  38. /// Loaded library in-memory data
  39. mmaps: BTreeMap<String, &'static mut [u8]>,
  40. verbose: bool,
  41. tls_index_offset: usize,
  42. }
  43. impl Linker {
  44. pub fn new(library_path: &str, verbose: bool) -> Self {
  45. Self {
  46. library_path: library_path.to_string(),
  47. objects: BTreeMap::new(),
  48. globals: BTreeMap::new(),
  49. weak_syms: BTreeMap::new(),
  50. mmaps: BTreeMap::new(),
  51. verbose,
  52. tls_index_offset: 0,
  53. }
  54. }
  55. pub fn load(&mut self, name: &str, path: &str) -> Result<()> {
  56. if self.verbose {
  57. println!("load {}: {}", name, path);
  58. }
  59. let mut data = Vec::new();
  60. let path_c = CString::new(path)
  61. .map_err(|err| Error::Malformed(format!("invalid path '{}': {}", path, err)))?;
  62. {
  63. let flags = fcntl::O_RDONLY | fcntl::O_CLOEXEC;
  64. let mut file = File::open(&path_c, flags)
  65. .map_err(|err| Error::Malformed(format!("failed to open '{}': {}", path, err)))?;
  66. file.read_to_end(&mut data)
  67. .map_err(|err| Error::Malformed(format!("failed to read '{}': {}", path, err)))?;
  68. }
  69. self.load_data(name, data.into_boxed_slice())
  70. }
  71. pub fn load_data(&mut self, name: &str, data: Box<[u8]>) -> Result<()> {
  72. //TODO: Prevent failures due to recursion
  73. {
  74. let elf = Elf::parse(&data)?;
  75. //println!("{:#?}", elf);
  76. for library in elf.libraries.iter() {
  77. self.load_library(library)?;
  78. }
  79. }
  80. self.objects.insert(name.to_string(), data);
  81. Ok(())
  82. }
  83. pub fn load_library(&mut self, name: &str) -> Result<()> {
  84. if self.objects.contains_key(name) {
  85. Ok(())
  86. } else if name.contains('/') {
  87. self.load(name, name)
  88. } else {
  89. let library_path = self.library_path.clone();
  90. for part in library_path.split(PATH_SEP) {
  91. let path = if part.is_empty() {
  92. format!("./{}", name)
  93. } else {
  94. format!("{}/{}", part, name)
  95. };
  96. if self.verbose {
  97. println!("check {}", path);
  98. }
  99. let access = unsafe {
  100. let path_c = CString::new(path.as_bytes()).map_err(|err| {
  101. Error::Malformed(format!("invalid path '{}': {}", path, err))
  102. })?;
  103. // TODO: Use R_OK | X_OK
  104. unistd::access(path_c.as_ptr(), unistd::F_OK) == 0
  105. };
  106. if access {
  107. self.load(name, &path)?;
  108. return Ok(());
  109. }
  110. }
  111. Err(Error::Malformed(format!("failed to locate '{}'", name)))
  112. }
  113. }
  114. fn collect_syms(
  115. elf: &Elf,
  116. mmap: &[u8],
  117. verbose: bool,
  118. ) -> Result<(BTreeMap<String, usize>, BTreeMap<String, usize>)> {
  119. let mut globals = BTreeMap::new();
  120. let mut weak_syms = BTreeMap::new();
  121. for sym in elf.dynsyms.iter() {
  122. let bind = sym.st_bind();
  123. if sym.st_value == 0 || ![sym::STB_GLOBAL, sym::STB_WEAK].contains(&bind) {
  124. continue;
  125. }
  126. let name: String;
  127. let value: usize;
  128. if let Some(name_res) = elf.dynstrtab.get(sym.st_name) {
  129. name = name_res?.to_string();
  130. value = mmap.as_ptr() as usize + sym.st_value as usize;
  131. } else {
  132. continue;
  133. }
  134. match sym.st_bind() {
  135. sym::STB_GLOBAL => {
  136. if verbose {
  137. println!(" global {}: {:x?} = {:#x}", &name, sym, value);
  138. }
  139. globals.insert(name, value);
  140. }
  141. sym::STB_WEAK => {
  142. if verbose {
  143. println!(" weak {}: {:x?} = {:#x}", &name, sym, value);
  144. }
  145. weak_syms.insert(name, value);
  146. }
  147. _ => unreachable!(),
  148. }
  149. }
  150. return Ok((globals, weak_syms));
  151. }
  152. pub fn get_sym(&self, name: &str) -> Option<usize> {
  153. if let Some(value) = self.globals.get(name) {
  154. if self.verbose {
  155. println!(" sym {} = {:#x}", name, value);
  156. }
  157. Some(*value)
  158. } else if let Some(value) = self.weak_syms.get(name) {
  159. if self.verbose {
  160. println!(" sym {} = {:#x}", name, value);
  161. }
  162. Some(*value)
  163. } else {
  164. if self.verbose {
  165. println!(" sym {} = undefined", name);
  166. }
  167. None
  168. }
  169. }
  170. pub fn link(&mut self, primary_opt: Option<&str>) -> Result<Option<usize>> {
  171. let elfs = {
  172. let mut elfs = BTreeMap::new();
  173. for (name, data) in self.objects.iter() {
  174. // Skip already linked libraries
  175. if !self.mmaps.contains_key(&*name) {
  176. elfs.insert(name.as_str(), Elf::parse(&data)?);
  177. }
  178. }
  179. elfs
  180. };
  181. // Load all ELF files into memory and find all globals
  182. let mut tls_primary = 0;
  183. let mut tls_size = 0;
  184. for (elf_name, elf) in elfs.iter() {
  185. if self.verbose {
  186. println!("map {}", elf_name);
  187. }
  188. let object = match self.objects.get(*elf_name) {
  189. Some(some) => some,
  190. None => continue,
  191. };
  192. // Calculate virtual memory bounds
  193. let bounds = {
  194. let mut bounds_opt: Option<(usize, usize)> = None;
  195. for ph in elf.program_headers.iter() {
  196. let voff = ph.p_vaddr as usize % PAGE_SIZE;
  197. let vaddr = ph.p_vaddr as usize - voff;
  198. let vsize =
  199. ((ph.p_memsz as usize + voff + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE;
  200. match ph.p_type {
  201. program_header::PT_LOAD => {
  202. if self.verbose {
  203. println!(" load {:#x}, {:#x}: {:x?}", vaddr, vsize, ph);
  204. }
  205. if let Some(ref mut bounds) = bounds_opt {
  206. if vaddr < bounds.0 {
  207. bounds.0 = vaddr;
  208. }
  209. if vaddr + vsize > bounds.1 {
  210. bounds.1 = vaddr + vsize;
  211. }
  212. } else {
  213. bounds_opt = Some((vaddr, vaddr + vsize));
  214. }
  215. }
  216. program_header::PT_TLS => {
  217. if self.verbose {
  218. println!(" load tls {:#x}: {:x?}", vsize, ph);
  219. }
  220. tls_size += vsize;
  221. if Some(*elf_name) == primary_opt {
  222. tls_primary += vsize;
  223. }
  224. }
  225. _ => (),
  226. }
  227. }
  228. match bounds_opt {
  229. Some(some) => some,
  230. None => continue,
  231. }
  232. };
  233. if self.verbose {
  234. println!(" bounds {:#x}, {:#x}", bounds.0, bounds.1);
  235. }
  236. // Allocate memory
  237. let mmap = unsafe {
  238. let size = bounds.1 /* - bounds.0 */;
  239. let ptr = sys_mman::mmap(
  240. ptr::null_mut(),
  241. size,
  242. //TODO: Make it possible to not specify PROT_EXEC on Redox
  243. sys_mman::PROT_READ | sys_mman::PROT_WRITE,
  244. sys_mman::MAP_ANONYMOUS | sys_mman::MAP_PRIVATE,
  245. -1,
  246. 0,
  247. );
  248. if ptr as usize == !0
  249. /* MAP_FAILED */
  250. {
  251. return Err(Error::Malformed(format!("failed to map {}", elf_name)));
  252. }
  253. ptr::write_bytes(ptr as *mut u8, 0, size);
  254. slice::from_raw_parts_mut(ptr as *mut u8, size)
  255. };
  256. if self.verbose {
  257. println!(" mmap {:p}, {:#x}", mmap.as_mut_ptr(), mmap.len());
  258. }
  259. let (globals, weak_syms) = Linker::collect_syms(&elf, &mmap, self.verbose)?;
  260. self.globals.extend(globals.into_iter());
  261. self.weak_syms.extend(weak_syms.into_iter());
  262. self.mmaps.insert(elf_name.to_string(), mmap);
  263. }
  264. // Allocate TLS
  265. let mut tcb_opt = if primary_opt.is_some() {
  266. Some(unsafe { Tcb::new(tls_size)? })
  267. } else {
  268. None
  269. };
  270. if self.verbose {
  271. println!("tcb {:x?}", tcb_opt);
  272. }
  273. // Copy data
  274. let mut tls_offset = tls_primary;
  275. let mut tcb_masters = Vec::new();
  276. // Insert main image master
  277. tcb_masters.push(Master {
  278. ptr: ptr::null_mut(),
  279. len: 0,
  280. offset: 0,
  281. });
  282. let mut tls_ranges = BTreeMap::new();
  283. for (elf_name, elf) in elfs.iter() {
  284. let object = match self.objects.get(*elf_name) {
  285. Some(some) => some,
  286. None => continue,
  287. };
  288. let mmap = match self.mmaps.get_mut(*elf_name) {
  289. Some(some) => some,
  290. None => continue,
  291. };
  292. if self.verbose {
  293. println!("load {}", elf_name);
  294. }
  295. // Copy data
  296. for ph in elf.program_headers.iter() {
  297. let voff = ph.p_vaddr as usize % PAGE_SIZE;
  298. let vaddr = ph.p_vaddr as usize - voff;
  299. let vsize = ((ph.p_memsz as usize + voff + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE;
  300. match ph.p_type {
  301. program_header::PT_LOAD => {
  302. let obj_data = {
  303. let range = ph.file_range();
  304. match object.get(range.clone()) {
  305. Some(some) => some,
  306. None => {
  307. return Err(Error::Malformed(format!(
  308. "failed to read {:?}",
  309. range
  310. )))
  311. }
  312. }
  313. };
  314. let mmap_data = {
  315. let range = ph.p_vaddr as usize..ph.p_vaddr as usize + obj_data.len();
  316. match mmap.get_mut(range.clone()) {
  317. Some(some) => some,
  318. None => {
  319. return Err(Error::Malformed(format!(
  320. "failed to write {:?}",
  321. range
  322. )))
  323. }
  324. }
  325. };
  326. if self.verbose {
  327. println!(
  328. " copy {:#x}, {:#x}: {:#x}, {:#x}",
  329. vaddr,
  330. vsize,
  331. voff,
  332. obj_data.len()
  333. );
  334. }
  335. mmap_data.copy_from_slice(obj_data);
  336. }
  337. program_header::PT_TLS => {
  338. let valign = if ph.p_align > 0 {
  339. ((ph.p_memsz + (ph.p_align - 1)) / ph.p_align) * ph.p_align
  340. } else {
  341. ph.p_memsz
  342. } as usize;
  343. let mut tcb_master = Master {
  344. ptr: unsafe { mmap.as_ptr().add(ph.p_vaddr as usize) },
  345. len: ph.p_filesz as usize,
  346. offset: tls_size - valign,
  347. };
  348. if self.verbose {
  349. println!(
  350. " tls master {:p}, {:#x}: {:#x}, {:#x}",
  351. tcb_master.ptr, tcb_master.len, tcb_master.offset, valign,
  352. );
  353. }
  354. if Some(*elf_name) == primary_opt {
  355. tls_ranges.insert(
  356. elf_name.to_string(),
  357. (self.tls_index_offset, tcb_master.range()),
  358. );
  359. tcb_masters[0] = tcb_master;
  360. } else {
  361. tcb_master.offset -= tls_offset;
  362. tls_offset += vsize;
  363. tls_ranges.insert(
  364. elf_name.to_string(),
  365. (
  366. self.tls_index_offset + tcb_masters.len(),
  367. tcb_master.range(),
  368. ),
  369. );
  370. tcb_masters.push(tcb_master);
  371. }
  372. }
  373. _ => (),
  374. }
  375. }
  376. }
  377. self.tls_index_offset += tcb_masters.len();
  378. // Set master images for TLS and copy TLS data
  379. if let Some(ref mut tcb) = tcb_opt {
  380. unsafe {
  381. tcb.set_masters(tcb_masters.into_boxed_slice());
  382. tcb.copy_masters()?;
  383. }
  384. }
  385. // Perform relocations, and protect pages
  386. for (elf_name, elf) in elfs.iter() {
  387. if self.verbose {
  388. println!("link {}", elf_name);
  389. }
  390. // Relocate
  391. for rel in elf
  392. .dynrelas
  393. .iter()
  394. .chain(elf.dynrels.iter())
  395. .chain(elf.pltrelocs.iter())
  396. {
  397. // println!(" rel {}: {:x?}",
  398. // reloc::r_to_str(rel.r_type, elf.header.e_machine),
  399. // rel
  400. // );
  401. let s = if rel.r_sym > 0 {
  402. let sym = elf.dynsyms.get(rel.r_sym).ok_or(Error::Malformed(format!(
  403. "missing symbol for relocation {:?}",
  404. rel
  405. )))?;
  406. let name =
  407. elf.dynstrtab
  408. .get(sym.st_name)
  409. .ok_or(Error::Malformed(format!(
  410. "missing name for symbol {:?}",
  411. sym
  412. )))??;
  413. self.get_sym(name).unwrap_or(0)
  414. } else {
  415. 0
  416. };
  417. let a = rel.r_addend.unwrap_or(0) as usize;
  418. let mmap = match self.mmaps.get_mut(*elf_name) {
  419. Some(some) => some,
  420. None => continue,
  421. };
  422. let b = mmap.as_mut_ptr() as usize;
  423. let (tm, t) = if let Some((tls_index, tls_range)) = tls_ranges.get(*elf_name) {
  424. (*tls_index, tls_range.start)
  425. } else {
  426. (0, 0)
  427. };
  428. let ptr = unsafe { mmap.as_mut_ptr().add(rel.r_offset as usize) };
  429. let set_u64 = |value| {
  430. // println!(" set_u64 {:#x}", value);
  431. unsafe {
  432. *(ptr as *mut u64) = value;
  433. }
  434. };
  435. match rel.r_type {
  436. reloc::R_X86_64_64 => {
  437. set_u64((s + a) as u64);
  438. }
  439. reloc::R_X86_64_DTPMOD64 => {
  440. set_u64(tm as u64);
  441. }
  442. reloc::R_X86_64_DTPOFF64 => {
  443. set_u64((s + a) as u64);
  444. }
  445. reloc::R_X86_64_GLOB_DAT | reloc::R_X86_64_JUMP_SLOT => {
  446. set_u64(s as u64);
  447. }
  448. reloc::R_X86_64_RELATIVE => {
  449. set_u64((b + a) as u64);
  450. }
  451. reloc::R_X86_64_TPOFF64 => {
  452. set_u64((s + a).wrapping_sub(t) as u64);
  453. }
  454. reloc::R_X86_64_IRELATIVE => (), // Handled below
  455. _ => {
  456. panic!(
  457. " {} unsupported",
  458. reloc::r_to_str(rel.r_type, elf.header.e_machine)
  459. );
  460. }
  461. }
  462. }
  463. // Protect pages
  464. for ph in elf.program_headers.iter() {
  465. if ph.p_type == program_header::PT_LOAD {
  466. let voff = ph.p_vaddr as usize % PAGE_SIZE;
  467. let vaddr = ph.p_vaddr as usize - voff;
  468. let vsize =
  469. ((ph.p_memsz as usize + voff + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE;
  470. let mut prot = 0;
  471. if ph.p_flags & program_header::PF_R == program_header::PF_R {
  472. prot |= sys_mman::PROT_READ;
  473. }
  474. // W ^ X. If it is executable, do not allow it to be writable, even if requested
  475. if ph.p_flags & program_header::PF_X == program_header::PF_X {
  476. prot |= sys_mman::PROT_EXEC;
  477. } else if ph.p_flags & program_header::PF_W == program_header::PF_W {
  478. prot |= sys_mman::PROT_WRITE;
  479. }
  480. let mmap = match self.mmaps.get_mut(*elf_name) {
  481. Some(some) => some,
  482. None => continue,
  483. };
  484. let res = unsafe {
  485. let ptr = mmap.as_mut_ptr().add(vaddr);
  486. if self.verbose {
  487. println!(" prot {:#x}, {:#x}: {:p}, {:#x}", vaddr, vsize, ptr, prot);
  488. }
  489. sys_mman::mprotect(ptr as *mut c_void, vsize, prot)
  490. };
  491. if res < 0 {
  492. return Err(Error::Malformed(format!("failed to mprotect {}", elf_name)));
  493. }
  494. }
  495. }
  496. }
  497. // Activate TLS
  498. if let Some(ref mut tcb) = tcb_opt {
  499. unsafe {
  500. tcb.activate();
  501. }
  502. }
  503. // Perform indirect relocations (necessary evil), gather entry point
  504. let mut entry_opt = None;
  505. for (elf_name, elf) in elfs.iter() {
  506. let mmap = match self.mmaps.get_mut(*elf_name) {
  507. Some(some) => some,
  508. None => continue,
  509. };
  510. if self.verbose {
  511. println!("entry {}", elf_name);
  512. }
  513. if Some(*elf_name) == primary_opt {
  514. entry_opt = Some(mmap.as_mut_ptr() as usize + elf.header.e_entry as usize);
  515. }
  516. // Relocate
  517. for rel in elf
  518. .dynrelas
  519. .iter()
  520. .chain(elf.dynrels.iter())
  521. .chain(elf.pltrelocs.iter())
  522. {
  523. // println!(" rel {}: {:x?}",
  524. // reloc::r_to_str(rel.r_type, elf.header.e_machine),
  525. // rel
  526. // );
  527. let a = rel.r_addend.unwrap_or(0) as usize;
  528. let b = mmap.as_mut_ptr() as usize;
  529. let ptr = unsafe { mmap.as_mut_ptr().add(rel.r_offset as usize) };
  530. let set_u64 = |value| {
  531. // println!(" set_u64 {:#x}", value);
  532. unsafe {
  533. *(ptr as *mut u64) = value;
  534. }
  535. };
  536. if rel.r_type == reloc::R_X86_64_IRELATIVE {
  537. unsafe {
  538. let f: unsafe extern "C" fn() -> u64 = mem::transmute(b + a);
  539. set_u64(f());
  540. }
  541. }
  542. }
  543. // Protect pages
  544. for ph in elf.program_headers.iter() {
  545. if let program_header::PT_LOAD = ph.p_type {
  546. let voff = ph.p_vaddr as usize % PAGE_SIZE;
  547. let vaddr = ph.p_vaddr as usize - voff;
  548. let vsize =
  549. ((ph.p_memsz as usize + voff + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE;
  550. let mut prot = 0;
  551. if ph.p_flags & program_header::PF_R == program_header::PF_R {
  552. prot |= sys_mman::PROT_READ;
  553. }
  554. // W ^ X. If it is executable, do not allow it to be writable, even if requested
  555. if ph.p_flags & program_header::PF_X == program_header::PF_X {
  556. prot |= sys_mman::PROT_EXEC;
  557. } else if ph.p_flags & program_header::PF_W == program_header::PF_W {
  558. prot |= sys_mman::PROT_WRITE;
  559. }
  560. let res = unsafe {
  561. let ptr = mmap.as_mut_ptr().add(vaddr);
  562. if self.verbose {
  563. println!(" prot {:#x}, {:#x}: {:p}, {:#x}", vaddr, vsize, ptr, prot);
  564. }
  565. sys_mman::mprotect(ptr as *mut c_void, vsize, prot)
  566. };
  567. if res < 0 {
  568. return Err(Error::Malformed(format!("failed to mprotect {}", elf_name)));
  569. }
  570. }
  571. }
  572. }
  573. Ok(entry_opt)
  574. }
  575. }