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