linker.rs 24 KB

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