elf.rs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909
  1. use core::{
  2. cmp::{max, min},
  3. fmt::Debug,
  4. intrinsics::{likely, unlikely},
  5. ops::Range,
  6. };
  7. use alloc::vec::Vec;
  8. use elf::{
  9. abi::{PT_GNU_PROPERTY, PT_INTERP},
  10. endian::AnyEndian,
  11. file::FileHeader,
  12. segment::ProgramHeader,
  13. };
  14. use system_error::SystemError;
  15. use crate::{
  16. arch::{CurrentElfArch, MMArch},
  17. driver::base::block::SeekFrom,
  18. filesystem::vfs::file::File,
  19. kerror,
  20. libs::align::page_align_up,
  21. mm::{
  22. allocator::page_frame::{PageFrameCount, VirtPageFrame},
  23. syscall::{MapFlags, ProtFlags},
  24. ucontext::InnerAddressSpace,
  25. MemoryManagementArch, VirtAddr,
  26. },
  27. process::{
  28. abi::AtType,
  29. exec::{BinaryLoader, BinaryLoaderResult, ExecError, ExecLoadMode, ExecParam},
  30. ProcessFlags, ProcessManager,
  31. },
  32. syscall::user_access::{clear_user, copy_to_user},
  33. };
  34. use super::rwlock::RwLockWriteGuard;
  35. // 存放跟架构相关的Elf属性,
  36. pub trait ElfArch: Clone + Copy + Debug {
  37. const ELF_ET_DYN_BASE: usize;
  38. const ELF_PAGE_SIZE: usize;
  39. }
  40. #[derive(Debug)]
  41. pub struct ElfLoader;
  42. pub const ELF_LOADER: ElfLoader = ElfLoader::new();
  43. impl ElfLoader {
  44. /// 读取文件的缓冲区大小
  45. pub const FILE_READ_BUF_SIZE: usize = 512 * 1024;
  46. pub const fn new() -> Self {
  47. Self
  48. }
  49. fn inner_probe_common(
  50. &self,
  51. param: &ExecParam,
  52. ehdr: &FileHeader<AnyEndian>,
  53. ) -> Result<(), ExecError> {
  54. // 只支持 64 位的 ELF 文件
  55. if ehdr.class != elf::file::Class::ELF64 {
  56. return Err(ExecError::WrongArchitecture);
  57. }
  58. // 判断是否以可执行文件的形式加载
  59. if param.load_mode() == ExecLoadMode::Exec {
  60. // 检查文件类型是否为可执行文件
  61. if ElfType::from(ehdr.e_type) != ElfType::Executable
  62. && ElfType::from(ehdr.e_type) != ElfType::DSO
  63. {
  64. return Err(ExecError::NotExecutable);
  65. }
  66. } else {
  67. return Err(ExecError::NotSupported);
  68. }
  69. return Ok(());
  70. }
  71. #[cfg(target_arch = "x86_64")]
  72. pub fn probe_x86_64(
  73. &self,
  74. param: &ExecParam,
  75. ehdr: &FileHeader<AnyEndian>,
  76. ) -> Result<(), ExecError> {
  77. // 判断架构是否匹配
  78. if ElfMachine::from(ehdr.e_machine) != ElfMachine::X86_64 {
  79. return Err(ExecError::WrongArchitecture);
  80. }
  81. return self.inner_probe_common(param, ehdr);
  82. }
  83. #[cfg(target_arch = "riscv64")]
  84. pub fn probe_riscv(
  85. &self,
  86. param: &ExecParam,
  87. ehdr: &FileHeader<AnyEndian>,
  88. ) -> Result<(), ExecError> {
  89. // 判断架构是否匹配
  90. if ElfMachine::from(ehdr.e_machine) != ElfMachine::RiscV {
  91. return Err(ExecError::WrongArchitecture);
  92. }
  93. return self.inner_probe_common(param, ehdr);
  94. }
  95. /// 设置用户堆空间,映射[start, end)区间的虚拟地址,并把brk指针指向end
  96. ///
  97. /// ## 参数
  98. ///
  99. /// - `user_vm_guard` - 用户虚拟地址空间
  100. /// - `start` - 本次映射的起始地址
  101. /// - `end` - 本次映射的结束地址(不包含)
  102. /// - `prot_flags` - 本次映射的权限
  103. fn set_elf_brk(
  104. &self,
  105. user_vm_guard: &mut RwLockWriteGuard<'_, InnerAddressSpace>,
  106. start: VirtAddr,
  107. end: VirtAddr,
  108. prot_flags: ProtFlags,
  109. ) -> Result<(), ExecError> {
  110. let start = self.elf_page_start(start);
  111. let end = self.elf_page_align_up(end);
  112. if end > start {
  113. let r = user_vm_guard.map_anonymous(
  114. start,
  115. end - start,
  116. prot_flags,
  117. MapFlags::MAP_ANONYMOUS | MapFlags::MAP_FIXED_NOREPLACE,
  118. false,
  119. );
  120. if r.is_err() {
  121. kerror!("set_elf_brk: map_anonymous failed, err={:?}", r);
  122. return Err(ExecError::OutOfMemory);
  123. }
  124. }
  125. user_vm_guard.elf_brk_start = end;
  126. user_vm_guard.elf_brk = end;
  127. return Ok(());
  128. }
  129. /// 计算addr在ELF PAGE内的偏移
  130. fn elf_page_offset(&self, addr: VirtAddr) -> usize {
  131. addr.data() & (CurrentElfArch::ELF_PAGE_SIZE - 1)
  132. }
  133. fn elf_page_start(&self, addr: VirtAddr) -> VirtAddr {
  134. VirtAddr::new(addr.data() & (!(CurrentElfArch::ELF_PAGE_SIZE - 1)))
  135. }
  136. fn elf_page_align_up(&self, addr: VirtAddr) -> VirtAddr {
  137. VirtAddr::new(
  138. (addr.data() + CurrentElfArch::ELF_PAGE_SIZE - 1)
  139. & (!(CurrentElfArch::ELF_PAGE_SIZE - 1)),
  140. )
  141. }
  142. /// 根据ELF的p_flags生成对应的ProtFlags
  143. fn make_prot(&self, p_flags: u32, _has_interpreter: bool, _is_interpreter: bool) -> ProtFlags {
  144. let mut prot = ProtFlags::empty();
  145. if p_flags & elf::abi::PF_R != 0 {
  146. prot |= ProtFlags::PROT_READ;
  147. }
  148. if p_flags & elf::abi::PF_W != 0 {
  149. prot |= ProtFlags::PROT_WRITE;
  150. }
  151. if p_flags & elf::abi::PF_X != 0 {
  152. prot |= ProtFlags::PROT_EXEC;
  153. }
  154. // todo: 增加与架构相关的处理
  155. // ref: https://code.dragonos.org.cn/xref/linux-5.19.10/fs/binfmt_elf.c?r=&mo=22652&fi=824#572
  156. return prot;
  157. }
  158. /// 加载ELF文件到用户空间
  159. ///
  160. /// 参考Linux的elf_map函数
  161. /// https://code.dragonos.org.cn/xref/linux-5.19.10/fs/binfmt_elf.c?r=&mo=22652&fi=824#365
  162. /// ## 参数
  163. ///
  164. /// - `user_vm_guard`:用户空间地址空间
  165. /// - `param`:执行参数
  166. /// - `phent`:ELF文件的ProgramHeader
  167. /// - `addr_to_map`:当前段应该被加载到的内存地址
  168. /// - `prot`:保护标志
  169. /// - `map_flags`:映射标志
  170. /// - `total_size`:ELF文件的总大小
  171. ///
  172. /// ## 返回值
  173. ///
  174. /// - `Ok((VirtAddr, bool))`:如果成功加载,则bool值为true,否则为false. VirtAddr为加载的地址
  175. #[allow(clippy::too_many_arguments)]
  176. fn load_elf_segment(
  177. &self,
  178. user_vm_guard: &mut RwLockWriteGuard<'_, InnerAddressSpace>,
  179. param: &mut ExecParam,
  180. phent: &ProgramHeader,
  181. mut addr_to_map: VirtAddr,
  182. prot: &ProtFlags,
  183. map_flags: &MapFlags,
  184. total_size: usize,
  185. ) -> Result<(VirtAddr, bool), SystemError> {
  186. // kdebug!("load_elf_segment: addr_to_map={:?}", addr_to_map);
  187. // 映射位置的偏移量(页内偏移)
  188. let beginning_page_offset = self.elf_page_offset(addr_to_map);
  189. addr_to_map = self.elf_page_start(addr_to_map);
  190. // 计算要映射的内存的大小
  191. let map_size = phent.p_filesz as usize + beginning_page_offset;
  192. let map_size = self.elf_page_align_up(VirtAddr::new(map_size)).data();
  193. // 当前段在文件中的大小
  194. let seg_in_file_size = phent.p_filesz as usize;
  195. // 当前段在文件中的偏移量
  196. let file_offset = phent.p_offset as usize;
  197. // 如果当前段的大小为0,则直接返回.
  198. // 段在文件中的大小为0,是合法的,但是段在内存中的大小不能为0
  199. if map_size == 0 {
  200. return Ok((addr_to_map, true));
  201. }
  202. let map_err_handler = |err: SystemError| {
  203. if err == SystemError::EEXIST {
  204. kerror!(
  205. "Pid: {:?}, elf segment at {:p} overlaps with existing mapping",
  206. ProcessManager::current_pcb().pid(),
  207. addr_to_map.as_ptr::<u8>()
  208. );
  209. }
  210. err
  211. };
  212. // 由于后面需要把ELF文件的内容加载到内存,因此暂时把当前段的权限设置为可写
  213. let tmp_prot = if !prot.contains(ProtFlags::PROT_WRITE) {
  214. *prot | ProtFlags::PROT_WRITE
  215. } else {
  216. *prot
  217. };
  218. // 映射到的虚拟地址。请注意,这个虚拟地址是user_vm_guard这个地址空间的虚拟地址。不一定是当前进程地址空间的
  219. let map_addr: VirtAddr;
  220. // total_size is the size of the ELF (interpreter) image.
  221. // The _first_ mmap needs to know the full size, otherwise
  222. // randomization might put this image into an overlapping
  223. // position with the ELF binary image. (since size < total_size)
  224. // So we first map the 'big' image - and unmap the remainder at
  225. // the end. (which unmap is needed for ELF images with holes.)
  226. if total_size != 0 {
  227. let total_size = self.elf_page_align_up(VirtAddr::new(total_size)).data();
  228. // kdebug!("total_size={}", total_size);
  229. map_addr = user_vm_guard
  230. .map_anonymous(addr_to_map, total_size, tmp_prot, *map_flags, false)
  231. .map_err(map_err_handler)?
  232. .virt_address();
  233. // kdebug!("map ok: addr_to_map={:?}", addr_to_map);
  234. let to_unmap = map_addr + map_size;
  235. let to_unmap_size = total_size - map_size;
  236. // kdebug!("to_unmap={:?}, to_unmap_size={}", to_unmap, to_unmap_size);
  237. user_vm_guard.munmap(
  238. VirtPageFrame::new(to_unmap),
  239. PageFrameCount::from_bytes(to_unmap_size).unwrap(),
  240. )?;
  241. // 加载文件到内存
  242. self.do_load_file(
  243. map_addr + beginning_page_offset,
  244. seg_in_file_size,
  245. file_offset,
  246. param,
  247. )?;
  248. if tmp_prot != *prot {
  249. user_vm_guard.mprotect(
  250. VirtPageFrame::new(map_addr),
  251. PageFrameCount::from_bytes(page_align_up(map_size)).unwrap(),
  252. *prot,
  253. )?;
  254. }
  255. } else {
  256. // kdebug!("total size = 0");
  257. map_addr = user_vm_guard
  258. .map_anonymous(addr_to_map, map_size, tmp_prot, *map_flags, false)?
  259. .virt_address();
  260. // kdebug!(
  261. // "map ok: addr_to_map={:?}, map_addr={map_addr:?},beginning_page_offset={beginning_page_offset:?}",
  262. // addr_to_map
  263. // );
  264. // 加载文件到内存
  265. self.do_load_file(
  266. map_addr + beginning_page_offset,
  267. seg_in_file_size,
  268. file_offset,
  269. param,
  270. )?;
  271. if tmp_prot != *prot {
  272. user_vm_guard.mprotect(
  273. VirtPageFrame::new(map_addr),
  274. PageFrameCount::from_bytes(page_align_up(map_size)).unwrap(),
  275. *prot,
  276. )?;
  277. }
  278. }
  279. // kdebug!("load_elf_segment OK: map_addr={:?}", map_addr);
  280. return Ok((map_addr, true));
  281. }
  282. /// 加载ELF文件到用户空间
  283. ///
  284. /// ## 参数
  285. ///
  286. /// - `vaddr`:要加载到的虚拟地址
  287. /// - `size`:要加载的大小
  288. /// - `offset_in_file`:在文件内的偏移量
  289. /// - `param`:执行参数
  290. fn do_load_file(
  291. &self,
  292. mut vaddr: VirtAddr,
  293. size: usize,
  294. offset_in_file: usize,
  295. param: &mut ExecParam,
  296. ) -> Result<(), SystemError> {
  297. let file = param.file_mut();
  298. if (file.metadata()?.size as usize) < offset_in_file + size {
  299. return Err(SystemError::ENOEXEC);
  300. }
  301. let buf_size = min(size, Self::FILE_READ_BUF_SIZE);
  302. let mut buf = vec![0u8; buf_size];
  303. let mut remain = size;
  304. file.lseek(SeekFrom::SeekSet(offset_in_file as i64))?;
  305. while remain > 0 {
  306. let read_size = min(remain, buf_size);
  307. file.read(read_size, &mut buf[..read_size])?;
  308. // kdebug!("copy_to_user: vaddr={:?}, read_size = {read_size}", vaddr);
  309. unsafe {
  310. copy_to_user(vaddr, &buf[..read_size]).map_err(|_| SystemError::EFAULT)?;
  311. }
  312. vaddr += read_size;
  313. remain -= read_size;
  314. }
  315. return Ok(());
  316. }
  317. /// 我们需要显式的把数据段之后剩余的内存页都清零。
  318. fn pad_zero(&self, elf_bss: VirtAddr) -> Result<(), SystemError> {
  319. let nbyte = self.elf_page_offset(elf_bss);
  320. if nbyte > 0 {
  321. let nbyte = CurrentElfArch::ELF_PAGE_SIZE - nbyte;
  322. unsafe { clear_user(elf_bss, nbyte).map_err(|_| SystemError::EFAULT) }?;
  323. }
  324. return Ok(());
  325. }
  326. /// 创建auxv
  327. ///
  328. /// ## 参数
  329. ///
  330. /// - `param`:执行参数
  331. /// - `entrypoint_vaddr`:程序入口地址
  332. /// - `phdr_vaddr`:程序头表地址
  333. /// - `elf_header`:ELF文件头
  334. fn create_auxv(
  335. &self,
  336. param: &mut ExecParam,
  337. entrypoint_vaddr: VirtAddr,
  338. phdr_vaddr: Option<VirtAddr>,
  339. ehdr: &elf::file::FileHeader<AnyEndian>,
  340. ) -> Result<(), ExecError> {
  341. let phdr_vaddr = phdr_vaddr.unwrap_or(VirtAddr::new(0));
  342. let init_info = param.init_info_mut();
  343. init_info
  344. .auxv
  345. .insert(AtType::PhEnt as u8, ehdr.e_phentsize as usize);
  346. init_info
  347. .auxv
  348. .insert(AtType::PageSize as u8, MMArch::PAGE_SIZE);
  349. init_info.auxv.insert(AtType::Phdr as u8, phdr_vaddr.data());
  350. init_info
  351. .auxv
  352. .insert(AtType::PhNum as u8, ehdr.e_phnum as usize);
  353. init_info
  354. .auxv
  355. .insert(AtType::Entry as u8, entrypoint_vaddr.data());
  356. return Ok(());
  357. }
  358. /// 解析文件的ehdr
  359. fn parse_ehdr(data: &[u8]) -> Result<FileHeader<AnyEndian>, elf::ParseError> {
  360. let ident_buf = data.get_bytes(0..elf::abi::EI_NIDENT)?;
  361. let ident = elf::file::parse_ident::<AnyEndian>(ident_buf)?;
  362. let tail_start = elf::abi::EI_NIDENT;
  363. let tail_end = match ident.1 {
  364. elf::file::Class::ELF32 => tail_start + elf::file::ELF32_EHDR_TAILSIZE,
  365. elf::file::Class::ELF64 => tail_start + elf::file::ELF64_EHDR_TAILSIZE,
  366. };
  367. let tail_buf = data.get_bytes(tail_start..tail_end)?;
  368. let ehdr: FileHeader<_> = FileHeader::parse_tail(ident, tail_buf)?;
  369. return Ok(ehdr);
  370. }
  371. /// 解析文件的program header table
  372. ///
  373. /// ## 参数
  374. ///
  375. /// - `param`:执行参数
  376. /// - `ehdr`:文件头
  377. /// - `data_buf`:用于缓存SegmentTable的Vec。
  378. /// 这是因为SegmentTable的生命周期与data_buf一致。初始化这个Vec的大小为0即可。
  379. ///
  380. /// ## 说明
  381. ///
  382. /// 这个函数由elf库的`elf::elf_bytes::find_phdrs`修改而来。
  383. fn parse_segments<'a>(
  384. param: &mut ExecParam,
  385. ehdr: &FileHeader<AnyEndian>,
  386. data_buf: &'a mut Vec<u8>,
  387. ) -> Result<Option<elf::segment::SegmentTable<'a, AnyEndian>>, elf::ParseError> {
  388. // It's Ok to have no program headers
  389. if ehdr.e_phoff == 0 {
  390. return Ok(None);
  391. }
  392. let file = param.file_mut();
  393. // If the number of segments is greater than or equal to PN_XNUM (0xffff),
  394. // e_phnum is set to PN_XNUM, and the actual number of program header table
  395. // entries is contained in the sh_info field of the section header at index 0.
  396. let mut phnum = ehdr.e_phnum as usize;
  397. if phnum == elf::abi::PN_XNUM as usize {
  398. let shoff: usize = ehdr.e_shoff.try_into()?;
  399. // 从磁盘读取shdr的前2个entry
  400. file.lseek(SeekFrom::SeekSet(shoff as i64))
  401. .map_err(|_| elf::ParseError::BadOffset(shoff as u64))?;
  402. let shdr_buf_size = ehdr.e_shentsize * 2;
  403. let mut shdr_buf = vec![0u8; shdr_buf_size as usize];
  404. file.read(shdr_buf_size as usize, &mut shdr_buf)
  405. .map_err(|_| elf::ParseError::BadOffset(shoff as u64))?;
  406. let mut offset = 0;
  407. let shdr0 = <elf::section::SectionHeader as elf::parse::ParseAt>::parse_at(
  408. ehdr.endianness,
  409. ehdr.class,
  410. &mut offset,
  411. &shdr_buf,
  412. )?;
  413. phnum = shdr0.sh_info.try_into()?;
  414. }
  415. // Validate phentsize before trying to read the table so that we can error early for corrupted files
  416. let entsize = <ProgramHeader as elf::parse::ParseAt>::validate_entsize(
  417. ehdr.class,
  418. ehdr.e_phentsize as usize,
  419. )?;
  420. let phoff: usize = ehdr.e_phoff.try_into()?;
  421. let size = entsize
  422. .checked_mul(phnum)
  423. .ok_or(elf::ParseError::IntegerOverflow)?;
  424. phoff
  425. .checked_add(size)
  426. .ok_or(elf::ParseError::IntegerOverflow)?;
  427. // 读取program header table
  428. file.lseek(SeekFrom::SeekSet(phoff as i64))
  429. .map_err(|_| elf::ParseError::BadOffset(phoff as u64))?;
  430. data_buf.clear();
  431. data_buf.resize(size, 0);
  432. file.read(size, data_buf)
  433. .expect("read program header table failed");
  434. let buf = data_buf.get_bytes(0..size)?;
  435. return Ok(Some(elf::segment::SegmentTable::new(
  436. ehdr.endianness,
  437. ehdr.class,
  438. buf,
  439. )));
  440. }
  441. // 解析 PT_GNU_PROPERTY 类型的段
  442. // 参照 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#767
  443. fn parse_gnu_property() -> Result<(), ExecError> {
  444. return Ok(());
  445. }
  446. }
  447. impl BinaryLoader for ElfLoader {
  448. fn probe(&'static self, param: &ExecParam, buf: &[u8]) -> Result<(), ExecError> {
  449. // let elf_bytes =
  450. // ElfBytes::<AnyEndian>::minimal_parse(buf).map_err(|_| ExecError::NotExecutable)?;
  451. let ehdr = Self::parse_ehdr(buf).map_err(|_| ExecError::NotExecutable)?;
  452. #[cfg(target_arch = "x86_64")]
  453. return self.probe_x86_64(param, &ehdr);
  454. #[cfg(target_arch = "riscv64")]
  455. return self.probe_riscv(param, &ehdr);
  456. #[cfg(not(any(target_arch = "x86_64", target_arch = "riscv64")))]
  457. compile_error!("BinaryLoader: Unsupported architecture");
  458. }
  459. fn load(
  460. &'static self,
  461. param: &mut ExecParam,
  462. head_buf: &[u8],
  463. ) -> Result<BinaryLoaderResult, ExecError> {
  464. // 解析elf文件头
  465. let ehdr = Self::parse_ehdr(head_buf).map_err(|_| ExecError::NotExecutable)?;
  466. // 参考linux-5.19的load_elf_binary函数
  467. // https://code.dragonos.org.cn/xref/linux-5.19.10/fs/binfmt_elf.c?r=&mo=22652&fi=824#1034
  468. let elf_type = ElfType::from(ehdr.e_type);
  469. // kdebug!("ehdr = {:?}", ehdr);
  470. let binding = param.vm().clone();
  471. let mut user_vm = binding.write();
  472. // todo: 增加对user stack上的内存是否具有可执行权限的处理(方法:寻找phdr里面的PT_GNU_STACK段)
  473. // kdebug!("to parse segments");
  474. // 加载ELF文件并映射到用户空间
  475. let mut phdr_buf = Vec::new();
  476. let phdr_table = Self::parse_segments(param, &ehdr, &mut phdr_buf)
  477. .map_err(|_| ExecError::ParseError)?
  478. .ok_or(ExecError::ParseError)?;
  479. let mut _gnu_property_data: Option<ProgramHeader> = None;
  480. let interpreter: Option<File> = None;
  481. for seg in phdr_table {
  482. if seg.p_type == PT_GNU_PROPERTY {
  483. _gnu_property_data = Some(seg);
  484. continue;
  485. }
  486. if seg.p_type != PT_INTERP {
  487. continue;
  488. }
  489. // 接下来处理这个 .interpreter 段以及动态链接器
  490. // 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#881
  491. if seg.p_filesz > 4096 || seg.p_filesz < 2 {
  492. return Err(ExecError::NotExecutable);
  493. }
  494. let interpreter_ptr = unsafe {
  495. core::slice::from_raw_parts(
  496. seg.p_offset as *const u8,
  497. seg.p_filesz.try_into().unwrap(),
  498. )
  499. };
  500. let _interpreter_path = core::str::from_utf8(interpreter_ptr).map_err(|e| {
  501. ExecError::Other(format!(
  502. "Failed to parse the path of dynamic linker with error {}",
  503. e
  504. ))
  505. })?;
  506. //TODO 加入对动态链接器的加载,参照 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#890
  507. }
  508. if interpreter.is_some() {
  509. /* Some simple consistency checks for the interpreter */
  510. // 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#950
  511. }
  512. Self::parse_gnu_property()?;
  513. // kdebug!("loadable_sections = {:?}", loadable_sections);
  514. let mut elf_brk = VirtAddr::new(0);
  515. let mut elf_bss = VirtAddr::new(0);
  516. let mut start_code: Option<VirtAddr> = None;
  517. let mut end_code: Option<VirtAddr> = None;
  518. let mut start_data: Option<VirtAddr> = None;
  519. let mut end_data: Option<VirtAddr> = None;
  520. // 加载的时候的偏移量(这个偏移量在加载动态链接段的时候产生)
  521. let mut load_bias = 0usize;
  522. let mut bss_prot_flags = ProtFlags::empty();
  523. // 是否是第一个加载的段
  524. let mut first_pt_load = true;
  525. // program header的虚拟地址
  526. let mut phdr_vaddr: Option<VirtAddr> = None;
  527. let mut _reloc_func_desc = 0usize;
  528. // 参考https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#1158,获取要加载的total_size
  529. let mut has_load = false;
  530. let mut min_address = VirtAddr::new(usize::MAX);
  531. let mut max_address = VirtAddr::new(0usize);
  532. let loadable_sections = phdr_table
  533. .into_iter()
  534. .filter(|seg| seg.p_type == elf::abi::PT_LOAD);
  535. for seg_to_load in loadable_sections {
  536. min_address = min(
  537. min_address,
  538. self.elf_page_start(VirtAddr::new(seg_to_load.p_vaddr.try_into().unwrap())),
  539. );
  540. max_address = max(
  541. max_address,
  542. VirtAddr::new(
  543. (seg_to_load.p_vaddr + seg_to_load.p_memsz)
  544. .try_into()
  545. .unwrap(),
  546. ),
  547. );
  548. has_load = true;
  549. }
  550. let total_size = if has_load {
  551. max_address - min_address
  552. } else {
  553. 0
  554. };
  555. let loadable_sections = phdr_table
  556. .into_iter()
  557. .filter(|seg| seg.p_type == elf::abi::PT_LOAD);
  558. for seg_to_load in loadable_sections {
  559. // kdebug!("seg_to_load = {:?}", seg_to_load);
  560. if unlikely(elf_brk > elf_bss) {
  561. // kdebug!(
  562. // "to set brk, elf_brk = {:?}, elf_bss = {:?}",
  563. // elf_brk,
  564. // elf_bss
  565. // );
  566. self.set_elf_brk(
  567. &mut user_vm,
  568. elf_bss + load_bias,
  569. elf_brk + load_bias,
  570. bss_prot_flags,
  571. )?;
  572. let nbyte = self.elf_page_offset(elf_bss);
  573. if nbyte > 0 {
  574. let nbyte = min(CurrentElfArch::ELF_PAGE_SIZE - nbyte, elf_brk - elf_bss);
  575. unsafe {
  576. // This bss-zeroing can fail if the ELF file specifies odd protections.
  577. // So we don't check the return value.
  578. clear_user(elf_bss + load_bias, nbyte).ok();
  579. }
  580. }
  581. }
  582. // 生成ProtFlags.
  583. let elf_prot_flags = self.make_prot(seg_to_load.p_flags, interpreter.is_some(), false);
  584. let mut elf_map_flags = MapFlags::MAP_PRIVATE;
  585. let vaddr = VirtAddr::new(seg_to_load.p_vaddr.try_into().unwrap());
  586. #[allow(clippy::if_same_then_else)]
  587. if !first_pt_load {
  588. elf_map_flags.insert(MapFlags::MAP_FIXED_NOREPLACE);
  589. } else if elf_type == ElfType::Executable {
  590. /*
  591. * This logic is run once for the first LOAD Program
  592. * Header for ET_EXEC binaries. No special handling
  593. * is needed.
  594. */
  595. elf_map_flags.insert(MapFlags::MAP_FIXED_NOREPLACE);
  596. } else if elf_type == ElfType::DSO {
  597. // TODO: 支持动态链接
  598. if interpreter.is_some() {
  599. load_bias = CurrentElfArch::ELF_ET_DYN_BASE;
  600. if ProcessManager::current_pcb()
  601. .flags()
  602. .contains(ProcessFlags::RANDOMIZE)
  603. {
  604. //这里x86下需要一个随机加载的方法,但是很多架构,比如Risc-V都是0,就暂时不写了
  605. } else {
  606. load_bias = 0;
  607. }
  608. }
  609. load_bias = self
  610. .elf_page_start(VirtAddr::new(
  611. load_bias - TryInto::<usize>::try_into(seg_to_load.p_vaddr).unwrap(),
  612. ))
  613. .data();
  614. if total_size == 0 {
  615. return Err(ExecError::InvalidParemeter);
  616. }
  617. }
  618. // 加载这个段到用户空间
  619. let e = self
  620. .load_elf_segment(
  621. &mut user_vm,
  622. param,
  623. &seg_to_load,
  624. vaddr + load_bias,
  625. &elf_prot_flags,
  626. &elf_map_flags,
  627. total_size,
  628. )
  629. .map_err(|e| match e {
  630. SystemError::EFAULT => ExecError::BadAddress(None),
  631. SystemError::ENOMEM => ExecError::OutOfMemory,
  632. _ => ExecError::Other(format!("load_elf_segment failed: {:?}", e)),
  633. })?;
  634. // 如果地址不对,那么就报错
  635. if !e.1 {
  636. return Err(ExecError::BadAddress(Some(e.0)));
  637. }
  638. if first_pt_load {
  639. first_pt_load = false;
  640. if elf_type == ElfType::DSO {
  641. // todo: 在这里增加对load_bias和reloc_func_desc的更新代码
  642. load_bias += e.0.data()
  643. - self
  644. .elf_page_start(VirtAddr::new(
  645. load_bias
  646. + TryInto::<usize>::try_into(seg_to_load.p_vaddr).unwrap(),
  647. ))
  648. .data();
  649. _reloc_func_desc = load_bias;
  650. }
  651. }
  652. // kdebug!("seg_to_load.p_offset={}", seg_to_load.p_offset);
  653. // kdebug!("e_phoff={}", ehdr.e_phoff);
  654. // kdebug!("seg_to_load.p_filesz={}", seg_to_load.p_filesz);
  655. // Figure out which segment in the file contains the Program Header Table,
  656. // and map to the associated virtual address.
  657. if (seg_to_load.p_offset <= ehdr.e_phoff)
  658. && (ehdr.e_phoff < (seg_to_load.p_offset + seg_to_load.p_filesz))
  659. {
  660. phdr_vaddr = Some(VirtAddr::new(
  661. (ehdr.e_phoff - seg_to_load.p_offset + seg_to_load.p_vaddr) as usize,
  662. ));
  663. }
  664. let p_vaddr = VirtAddr::new(seg_to_load.p_vaddr as usize);
  665. if (seg_to_load.p_flags & elf::abi::PF_X) != 0
  666. && (start_code.is_none() || start_code.as_ref().unwrap() > &p_vaddr)
  667. {
  668. start_code = Some(p_vaddr);
  669. }
  670. if start_data.is_none()
  671. || (start_data.is_some() && start_data.as_ref().unwrap() > &p_vaddr)
  672. {
  673. start_data = Some(p_vaddr);
  674. }
  675. // 如果程序段要加载的目标地址不在用户空间内,或者是其他不合法的情况,那么就报错
  676. if !p_vaddr.check_user()
  677. || seg_to_load.p_filesz > seg_to_load.p_memsz
  678. || self.elf_page_align_up(p_vaddr + seg_to_load.p_memsz as usize)
  679. >= MMArch::USER_END_VADDR
  680. {
  681. // kdebug!("ERR: p_vaddr={p_vaddr:?}");
  682. return Err(ExecError::InvalidParemeter);
  683. }
  684. // end vaddr of this segment(code+data+bss)
  685. let seg_end_vaddr_f = self.elf_page_align_up(VirtAddr::new(
  686. (seg_to_load.p_vaddr + seg_to_load.p_filesz) as usize,
  687. ));
  688. if seg_end_vaddr_f > elf_bss {
  689. elf_bss = seg_end_vaddr_f;
  690. }
  691. if ((seg_to_load.p_flags & elf::abi::PF_X) != 0)
  692. && (end_code.is_none()
  693. || (end_code.is_some() && end_code.as_ref().unwrap() < &seg_end_vaddr_f))
  694. {
  695. end_code = Some(seg_end_vaddr_f);
  696. }
  697. if end_data.is_none()
  698. || (end_data.is_some() && end_data.as_ref().unwrap() < &seg_end_vaddr_f)
  699. {
  700. end_data = Some(seg_end_vaddr_f);
  701. }
  702. let seg_end_vaddr = VirtAddr::new((seg_to_load.p_vaddr + seg_to_load.p_memsz) as usize);
  703. if seg_end_vaddr > elf_brk {
  704. bss_prot_flags = elf_prot_flags;
  705. elf_brk = seg_end_vaddr;
  706. }
  707. }
  708. // kdebug!("elf load: phdr_vaddr={phdr_vaddr:?}");
  709. let program_entrypoint = VirtAddr::new(ehdr.e_entry as usize + load_bias);
  710. let phdr_vaddr = phdr_vaddr.map(|phdr_vaddr| phdr_vaddr + load_bias);
  711. elf_bss += load_bias;
  712. elf_brk += load_bias;
  713. start_code = start_code.map(|v| v + load_bias);
  714. end_code = end_code.map(|v| v + load_bias);
  715. start_data = start_data.map(|v| v + load_bias);
  716. end_data = end_data.map(|v| v + load_bias);
  717. // kdebug!(
  718. // "to set brk: elf_bss: {:?}, elf_brk: {:?}, bss_prot_flags: {:?}",
  719. // elf_bss,
  720. // elf_brk,
  721. // bss_prot_flags
  722. // );
  723. self.set_elf_brk(&mut user_vm, elf_bss, elf_brk, bss_prot_flags)?;
  724. if likely(elf_bss != elf_brk) && unlikely(self.pad_zero(elf_bss).is_err()) {
  725. // kdebug!("elf_bss = {elf_bss:?}, elf_brk = {elf_brk:?}");
  726. return Err(ExecError::BadAddress(Some(elf_bss)));
  727. }
  728. if interpreter.is_some() {
  729. // TODO 添加对动态加载器的处理
  730. // 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#1249
  731. }
  732. // kdebug!("to create auxv");
  733. self.create_auxv(param, program_entrypoint, phdr_vaddr, &ehdr)?;
  734. // kdebug!("auxv create ok");
  735. user_vm.start_code = start_code.unwrap_or(VirtAddr::new(0));
  736. user_vm.end_code = end_code.unwrap_or(VirtAddr::new(0));
  737. user_vm.start_data = start_data.unwrap_or(VirtAddr::new(0));
  738. user_vm.end_data = end_data.unwrap_or(VirtAddr::new(0));
  739. let result = BinaryLoaderResult::new(program_entrypoint);
  740. // kdebug!("elf load OK!!!");
  741. return Ok(result);
  742. }
  743. }
  744. /// Elf机器架构,对应于e_machine字段。在ABI中,以EM_开头的常量是e_machine字段的值。
  745. #[derive(Debug, Eq, PartialEq)]
  746. pub enum ElfMachine {
  747. I386,
  748. AArch32,
  749. AArch64,
  750. X86_64,
  751. RiscV,
  752. /// 龙芯架构
  753. LoongArch,
  754. /// 未知架构
  755. Unknown,
  756. }
  757. impl From<u16> for ElfMachine {
  758. fn from(machine: u16) -> Self {
  759. match machine {
  760. 0x03 => Self::I386,
  761. 0x28 => Self::AArch32,
  762. 0xb7 => Self::AArch64,
  763. 0x3e => Self::X86_64,
  764. 0xf3 => Self::RiscV,
  765. 0x102 => Self::LoongArch,
  766. // 未知架构
  767. _ => Self::Unknown,
  768. }
  769. }
  770. }
  771. /// Elf文件类型,对应于e_type字段。在ABI中,以ET_开头的常量是e_type字段的值。
  772. #[derive(Debug, Eq, PartialEq)]
  773. pub enum ElfType {
  774. /// 可重定位文件
  775. Relocatable,
  776. /// 可执行文件
  777. Executable,
  778. /// 动态链接库
  779. DSO,
  780. /// 核心转储文件
  781. Core,
  782. /// 未知类型
  783. Unknown,
  784. }
  785. impl From<u16> for ElfType {
  786. fn from(elf_type: u16) -> Self {
  787. match elf_type {
  788. 0x01 => Self::Relocatable,
  789. 0x02 => Self::Executable,
  790. 0x03 => Self::DSO,
  791. 0x04 => Self::Core,
  792. _ => Self::Unknown,
  793. }
  794. }
  795. }
  796. // Simple convenience extension trait to wrap get() with .ok_or(SliceReadError)
  797. trait ReadBytesExt<'data> {
  798. fn get_bytes(self, range: Range<usize>) -> Result<&'data [u8], elf::ParseError>;
  799. }
  800. impl<'data> ReadBytesExt<'data> for &'data [u8] {
  801. fn get_bytes(self, range: Range<usize>) -> Result<&'data [u8], elf::ParseError> {
  802. let start = range.start;
  803. let end = range.end;
  804. self.get(range)
  805. .ok_or(elf::ParseError::SliceReadError((start, end)))
  806. }
  807. }