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