elf.rs 28 KB

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