mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-18 16:26:31 +00:00
支持对动态链接文件的加载,支持通过musl工具链编写用户空间程序 (#504)
支持对动态链接文件的加载,支持通过musl工具链编写用户空间程序
This commit is contained in:
10
kernel/src/arch/riscv64/elf.rs
Normal file
10
kernel/src/arch/riscv64/elf.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
use crate::{arch::MMArch, libs::elf::ElfArch, mm::MemoryManagementArch};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Hash)]
|
||||||
|
pub struct RiscV64ElfArch;
|
||||||
|
|
||||||
|
impl ElfArch for RiscV64ElfArch {
|
||||||
|
const ELF_ET_DYN_BASE: usize = MMArch::USER_END_VADDR.data() / 3 * 2;
|
||||||
|
|
||||||
|
const ELF_PAGE_SIZE: usize = MMArch::PAGE_SIZE;
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
pub mod asm;
|
pub mod asm;
|
||||||
pub mod cpu;
|
pub mod cpu;
|
||||||
pub mod driver;
|
pub mod driver;
|
||||||
|
pub mod elf;
|
||||||
pub mod init;
|
pub mod init;
|
||||||
pub mod interrupt;
|
pub mod interrupt;
|
||||||
pub mod ipc;
|
pub mod ipc;
|
||||||
@ -21,3 +22,5 @@ pub use self::mm::RiscV64MMArch as MMArch;
|
|||||||
pub use self::pci::RiscV64PciArch as PciArch;
|
pub use self::pci::RiscV64PciArch as PciArch;
|
||||||
pub use self::pio::RiscV64PortIOArch as CurrentPortIOArch;
|
pub use self::pio::RiscV64PortIOArch as CurrentPortIOArch;
|
||||||
pub use self::time::RiscV64TimeArch as CurrentTimeArch;
|
pub use self::time::RiscV64TimeArch as CurrentTimeArch;
|
||||||
|
|
||||||
|
pub use self::elf::RiscV64ElfArch as CurrentElfArch;
|
||||||
|
10
kernel/src/arch/x86_64/elf.rs
Normal file
10
kernel/src/arch/x86_64/elf.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
use crate::{arch::MMArch, libs::elf::ElfArch, mm::MemoryManagementArch};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Hash)]
|
||||||
|
pub struct X86_64ElfArch;
|
||||||
|
|
||||||
|
impl ElfArch for X86_64ElfArch {
|
||||||
|
const ELF_ET_DYN_BASE: usize = MMArch::USER_END_VADDR.data() / 3 * 2;
|
||||||
|
|
||||||
|
const ELF_PAGE_SIZE: usize = MMArch::PAGE_SIZE;
|
||||||
|
}
|
@ -4,6 +4,7 @@ mod acpi;
|
|||||||
mod c_adapter;
|
mod c_adapter;
|
||||||
pub mod cpu;
|
pub mod cpu;
|
||||||
pub mod driver;
|
pub mod driver;
|
||||||
|
pub mod elf;
|
||||||
pub mod fpu;
|
pub mod fpu;
|
||||||
pub mod init;
|
pub mod init;
|
||||||
pub mod interrupt;
|
pub mod interrupt;
|
||||||
@ -33,3 +34,5 @@ pub use kvm::X86_64KVMArch as KVMArch;
|
|||||||
|
|
||||||
pub use crate::arch::ipc::signal::X86_64SignalArch as CurrentSignalArch;
|
pub use crate::arch::ipc::signal::X86_64SignalArch as CurrentSignalArch;
|
||||||
pub use crate::arch::time::X86_64TimeArch as CurrentTimeArch;
|
pub use crate::arch::time::X86_64TimeArch as CurrentTimeArch;
|
||||||
|
|
||||||
|
pub use crate::arch::elf::X86_64ElfArch as CurrentElfArch;
|
||||||
|
@ -63,7 +63,7 @@ impl Syscall {
|
|||||||
drop(old_address_space);
|
drop(old_address_space);
|
||||||
drop(irq_guard);
|
drop(irq_guard);
|
||||||
// kdebug!("to load binary file");
|
// kdebug!("to load binary file");
|
||||||
let mut param = ExecParam::new(path.as_str(), address_space.clone(), ExecParamFlags::EXEC);
|
let mut param = ExecParam::new(path.as_str(), address_space.clone(), ExecParamFlags::EXEC)?;
|
||||||
|
|
||||||
// 加载可执行文件
|
// 加载可执行文件
|
||||||
let load_result = load_binary_file(&mut param)
|
let load_result = load_binary_file(&mut param)
|
||||||
|
@ -1,16 +1,23 @@
|
|||||||
use core::{
|
use core::{
|
||||||
cmp::min,
|
cmp::{max, min},
|
||||||
|
fmt::Debug,
|
||||||
intrinsics::{likely, unlikely},
|
intrinsics::{likely, unlikely},
|
||||||
ops::Range,
|
ops::Range,
|
||||||
};
|
};
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use elf::{endian::AnyEndian, file::FileHeader, segment::ProgramHeader};
|
use elf::{
|
||||||
|
abi::{PT_GNU_PROPERTY, PT_INTERP},
|
||||||
|
endian::AnyEndian,
|
||||||
|
file::FileHeader,
|
||||||
|
segment::ProgramHeader,
|
||||||
|
};
|
||||||
use system_error::SystemError;
|
use system_error::SystemError;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::MMArch,
|
arch::{CurrentElfArch, MMArch},
|
||||||
driver::base::block::SeekFrom,
|
driver::base::block::SeekFrom,
|
||||||
|
filesystem::vfs::file::File,
|
||||||
kerror,
|
kerror,
|
||||||
libs::align::page_align_up,
|
libs::align::page_align_up,
|
||||||
mm::{
|
mm::{
|
||||||
@ -22,22 +29,25 @@ use crate::{
|
|||||||
process::{
|
process::{
|
||||||
abi::AtType,
|
abi::AtType,
|
||||||
exec::{BinaryLoader, BinaryLoaderResult, ExecError, ExecLoadMode, ExecParam},
|
exec::{BinaryLoader, BinaryLoaderResult, ExecError, ExecLoadMode, ExecParam},
|
||||||
ProcessManager,
|
ProcessFlags, ProcessManager,
|
||||||
},
|
},
|
||||||
syscall::user_access::{clear_user, copy_to_user},
|
syscall::user_access::{clear_user, copy_to_user},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::rwlock::RwLockWriteGuard;
|
use super::rwlock::RwLockWriteGuard;
|
||||||
|
|
||||||
|
// 存放跟架构相关的Elf属性,
|
||||||
|
pub trait ElfArch: Clone + Copy + Debug {
|
||||||
|
const ELF_ET_DYN_BASE: usize;
|
||||||
|
const ELF_PAGE_SIZE: usize;
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ElfLoader;
|
pub struct ElfLoader;
|
||||||
|
|
||||||
pub const ELF_LOADER: ElfLoader = ElfLoader::new();
|
pub const ELF_LOADER: ElfLoader = ElfLoader::new();
|
||||||
|
|
||||||
impl ElfLoader {
|
impl ElfLoader {
|
||||||
#[cfg(any(target_arch = "x86_64", target_arch = "riscv64"))]
|
|
||||||
pub const ELF_PAGE_SIZE: usize = MMArch::PAGE_SIZE;
|
|
||||||
|
|
||||||
/// 读取文件的缓冲区大小
|
/// 读取文件的缓冲区大小
|
||||||
pub const FILE_READ_BUF_SIZE: usize = 512 * 1024;
|
pub const FILE_READ_BUF_SIZE: usize = 512 * 1024;
|
||||||
|
|
||||||
@ -58,7 +68,9 @@ impl ElfLoader {
|
|||||||
// 判断是否以可执行文件的形式加载
|
// 判断是否以可执行文件的形式加载
|
||||||
if param.load_mode() == ExecLoadMode::Exec {
|
if param.load_mode() == ExecLoadMode::Exec {
|
||||||
// 检查文件类型是否为可执行文件
|
// 检查文件类型是否为可执行文件
|
||||||
if ElfType::from(ehdr.e_type) != ElfType::Executable {
|
if ElfType::from(ehdr.e_type) != ElfType::Executable
|
||||||
|
&& ElfType::from(ehdr.e_type) != ElfType::DSO
|
||||||
|
{
|
||||||
return Err(ExecError::NotExecutable);
|
return Err(ExecError::NotExecutable);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -132,15 +144,18 @@ impl ElfLoader {
|
|||||||
|
|
||||||
/// 计算addr在ELF PAGE内的偏移
|
/// 计算addr在ELF PAGE内的偏移
|
||||||
fn elf_page_offset(&self, addr: VirtAddr) -> usize {
|
fn elf_page_offset(&self, addr: VirtAddr) -> usize {
|
||||||
addr.data() & (Self::ELF_PAGE_SIZE - 1)
|
addr.data() & (CurrentElfArch::ELF_PAGE_SIZE - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn elf_page_start(&self, addr: VirtAddr) -> VirtAddr {
|
fn elf_page_start(&self, addr: VirtAddr) -> VirtAddr {
|
||||||
VirtAddr::new(addr.data() & (!(Self::ELF_PAGE_SIZE - 1)))
|
VirtAddr::new(addr.data() & (!(CurrentElfArch::ELF_PAGE_SIZE - 1)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn elf_page_align_up(&self, addr: VirtAddr) -> VirtAddr {
|
fn elf_page_align_up(&self, addr: VirtAddr) -> VirtAddr {
|
||||||
VirtAddr::new((addr.data() + Self::ELF_PAGE_SIZE - 1) & (!(Self::ELF_PAGE_SIZE - 1)))
|
VirtAddr::new(
|
||||||
|
(addr.data() + CurrentElfArch::ELF_PAGE_SIZE - 1)
|
||||||
|
& (!(CurrentElfArch::ELF_PAGE_SIZE - 1)),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 根据ELF的p_flags生成对应的ProtFlags
|
/// 根据ELF的p_flags生成对应的ProtFlags
|
||||||
@ -343,7 +358,7 @@ impl ElfLoader {
|
|||||||
fn pad_zero(&self, elf_bss: VirtAddr) -> Result<(), SystemError> {
|
fn pad_zero(&self, elf_bss: VirtAddr) -> Result<(), SystemError> {
|
||||||
let nbyte = self.elf_page_offset(elf_bss);
|
let nbyte = self.elf_page_offset(elf_bss);
|
||||||
if nbyte > 0 {
|
if nbyte > 0 {
|
||||||
let nbyte = Self::ELF_PAGE_SIZE - nbyte;
|
let nbyte = CurrentElfArch::ELF_PAGE_SIZE - nbyte;
|
||||||
unsafe { clear_user(elf_bss, nbyte).map_err(|_| SystemError::EFAULT) }?;
|
unsafe { clear_user(elf_bss, nbyte).map_err(|_| SystemError::EFAULT) }?;
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@ -477,6 +492,12 @@ impl ElfLoader {
|
|||||||
buf,
|
buf,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 解析 PT_GNU_PROPERTY 类型的段
|
||||||
|
// 参照 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#767
|
||||||
|
fn parse_gnu_property() -> Result<(), ExecError> {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BinaryLoader for ElfLoader {
|
impl BinaryLoader for ElfLoader {
|
||||||
@ -515,16 +536,49 @@ impl BinaryLoader for ElfLoader {
|
|||||||
|
|
||||||
// todo: 增加对user stack上的内存是否具有可执行权限的处理(方法:寻找phdr里面的PT_GNU_STACK段)
|
// todo: 增加对user stack上的内存是否具有可执行权限的处理(方法:寻找phdr里面的PT_GNU_STACK段)
|
||||||
|
|
||||||
// todo: 增加对动态链接的处理
|
|
||||||
|
|
||||||
// kdebug!("to parse segments");
|
// kdebug!("to parse segments");
|
||||||
// 加载ELF文件并映射到用户空间
|
// 加载ELF文件并映射到用户空间
|
||||||
let mut phdr_buf = Vec::new();
|
let mut phdr_buf = Vec::new();
|
||||||
let loadable_sections = Self::parse_segments(param, &ehdr, &mut phdr_buf)
|
let phdr_table = Self::parse_segments(param, &ehdr, &mut phdr_buf)
|
||||||
.map_err(|_| ExecError::ParseError)?
|
.map_err(|_| ExecError::ParseError)?
|
||||||
.ok_or(ExecError::ParseError)?
|
.ok_or(ExecError::ParseError)?;
|
||||||
.iter()
|
let mut _gnu_property_data: Option<ProgramHeader> = None;
|
||||||
.filter(|seg| seg.p_type == elf::abi::PT_LOAD);
|
let interpreter: Option<File> = None;
|
||||||
|
for seg in phdr_table {
|
||||||
|
if seg.p_type == PT_GNU_PROPERTY {
|
||||||
|
_gnu_property_data = Some(seg.clone());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if seg.p_type != PT_INTERP {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 接下来处理这个 .interpreter 段以及动态链接器
|
||||||
|
// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#881
|
||||||
|
|
||||||
|
if seg.p_filesz > 4096 || seg.p_filesz < 2 {
|
||||||
|
return Err(ExecError::NotExecutable);
|
||||||
|
}
|
||||||
|
|
||||||
|
let interpreter_ptr = unsafe {
|
||||||
|
core::slice::from_raw_parts(
|
||||||
|
seg.p_offset as *const u8,
|
||||||
|
seg.p_filesz.try_into().unwrap(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let _interpreter_path = core::str::from_utf8(interpreter_ptr).map_err(|e| {
|
||||||
|
ExecError::Other(format!(
|
||||||
|
"Failed to parse the path of dynamic linker with error {}",
|
||||||
|
e
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
//TODO 加入对动态链接器的加载,参照 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#890
|
||||||
|
}
|
||||||
|
if interpreter.is_some() {
|
||||||
|
/* Some simple consistency checks for the interpreter */
|
||||||
|
// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#950
|
||||||
|
}
|
||||||
|
Self::parse_gnu_property()?;
|
||||||
|
|
||||||
// kdebug!("loadable_sections = {:?}", loadable_sections);
|
// kdebug!("loadable_sections = {:?}", loadable_sections);
|
||||||
|
|
||||||
@ -535,14 +589,44 @@ impl BinaryLoader for ElfLoader {
|
|||||||
let mut start_data: Option<VirtAddr> = None;
|
let mut start_data: Option<VirtAddr> = None;
|
||||||
let mut end_data: Option<VirtAddr> = None;
|
let mut end_data: Option<VirtAddr> = None;
|
||||||
|
|
||||||
// 加载的时候的偏移量(这个偏移量在加载动态链接段的时候产生,由于还没有动态链接,因此暂时不可变。)
|
// 加载的时候的偏移量(这个偏移量在加载动态链接段的时候产生)
|
||||||
// 请不要删除load_bias! 以免到时候写动态链接的时候忘记了。
|
let mut load_bias = 0usize;
|
||||||
let load_bias = 0usize;
|
|
||||||
let mut bss_prot_flags = ProtFlags::empty();
|
let mut bss_prot_flags = ProtFlags::empty();
|
||||||
// 是否是第一个加载的段
|
// 是否是第一个加载的段
|
||||||
let mut first_pt_load = true;
|
let mut first_pt_load = true;
|
||||||
// program header的虚拟地址
|
// program header的虚拟地址
|
||||||
let mut phdr_vaddr: Option<VirtAddr> = None;
|
let mut phdr_vaddr: Option<VirtAddr> = None;
|
||||||
|
let mut _reloc_func_desc = 0usize;
|
||||||
|
// 参考https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#1158,获取要加载的total_size
|
||||||
|
let mut has_load = false;
|
||||||
|
let mut min_address = VirtAddr::new(usize::MAX);
|
||||||
|
let mut max_address = VirtAddr::new(0usize);
|
||||||
|
let loadable_sections = phdr_table
|
||||||
|
.into_iter()
|
||||||
|
.filter(|seg| seg.p_type == elf::abi::PT_LOAD);
|
||||||
|
for seg_to_load in loadable_sections {
|
||||||
|
min_address = min(
|
||||||
|
min_address,
|
||||||
|
self.elf_page_start(VirtAddr::new(seg_to_load.p_vaddr.try_into().unwrap())),
|
||||||
|
);
|
||||||
|
max_address = max(
|
||||||
|
max_address,
|
||||||
|
VirtAddr::new(
|
||||||
|
(seg_to_load.p_vaddr + seg_to_load.p_memsz)
|
||||||
|
.try_into()
|
||||||
|
.unwrap(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
has_load = true;
|
||||||
|
}
|
||||||
|
let total_size = if has_load {
|
||||||
|
max_address - min_address
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
let loadable_sections = phdr_table
|
||||||
|
.into_iter()
|
||||||
|
.filter(|seg| seg.p_type == elf::abi::PT_LOAD);
|
||||||
for seg_to_load in loadable_sections {
|
for seg_to_load in loadable_sections {
|
||||||
// kdebug!("seg_to_load = {:?}", seg_to_load);
|
// kdebug!("seg_to_load = {:?}", seg_to_load);
|
||||||
if unlikely(elf_brk > elf_bss) {
|
if unlikely(elf_brk > elf_bss) {
|
||||||
@ -559,7 +643,7 @@ impl BinaryLoader for ElfLoader {
|
|||||||
)?;
|
)?;
|
||||||
let nbyte = self.elf_page_offset(elf_bss);
|
let nbyte = self.elf_page_offset(elf_bss);
|
||||||
if nbyte > 0 {
|
if nbyte > 0 {
|
||||||
let nbyte = min(Self::ELF_PAGE_SIZE - nbyte, elf_brk - elf_bss);
|
let nbyte = min(CurrentElfArch::ELF_PAGE_SIZE - nbyte, elf_brk - elf_bss);
|
||||||
unsafe {
|
unsafe {
|
||||||
// This bss-zeroing can fail if the ELF file specifies odd protections.
|
// This bss-zeroing can fail if the ELF file specifies odd protections.
|
||||||
// So we don't check the return value.
|
// So we don't check the return value.
|
||||||
@ -569,12 +653,11 @@ impl BinaryLoader for ElfLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 生成ProtFlags.
|
// 生成ProtFlags.
|
||||||
// TODO: 当有了动态链接之后,需要根据情况设置这里的has_interpreter
|
let elf_prot_flags = self.make_prot(seg_to_load.p_flags, interpreter.is_some(), false);
|
||||||
let elf_prot_flags = self.make_prot(seg_to_load.p_flags, false, false);
|
|
||||||
|
|
||||||
let mut elf_map_flags = MapFlags::MAP_PRIVATE;
|
let mut elf_map_flags = MapFlags::MAP_PRIVATE;
|
||||||
|
|
||||||
let vaddr = VirtAddr::new(seg_to_load.p_vaddr as usize);
|
let vaddr = VirtAddr::new(seg_to_load.p_vaddr.try_into().unwrap());
|
||||||
|
|
||||||
if !first_pt_load {
|
if !first_pt_load {
|
||||||
elf_map_flags.insert(MapFlags::MAP_FIXED_NOREPLACE);
|
elf_map_flags.insert(MapFlags::MAP_FIXED_NOREPLACE);
|
||||||
@ -587,11 +670,28 @@ impl BinaryLoader for ElfLoader {
|
|||||||
elf_map_flags.insert(MapFlags::MAP_FIXED_NOREPLACE);
|
elf_map_flags.insert(MapFlags::MAP_FIXED_NOREPLACE);
|
||||||
} else if elf_type == ElfType::DSO {
|
} else if elf_type == ElfType::DSO {
|
||||||
// TODO: 支持动态链接
|
// TODO: 支持动态链接
|
||||||
unimplemented!("DragonOS currently does not support dynamic linking!");
|
if interpreter.is_some() {
|
||||||
|
load_bias = CurrentElfArch::ELF_ET_DYN_BASE;
|
||||||
|
if ProcessManager::current_pcb()
|
||||||
|
.flags()
|
||||||
|
.contains(ProcessFlags::RANDOMIZE)
|
||||||
|
{
|
||||||
|
//这里x86下需要一个随机加载的方法,但是很多架构,比如Risc-V都是0,就暂时不写了
|
||||||
|
} else {
|
||||||
|
load_bias = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
load_bias = self
|
||||||
|
.elf_page_start(VirtAddr::new(
|
||||||
|
load_bias - TryInto::<usize>::try_into(seg_to_load.p_vaddr).unwrap(),
|
||||||
|
))
|
||||||
|
.data();
|
||||||
|
if total_size == 0 {
|
||||||
|
return Err(ExecError::InvalidParemeter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载这个段到用户空间
|
// 加载这个段到用户空间
|
||||||
// todo: 引入动态链接后,这里的total_size要按照实际的填写,而不一定是0
|
|
||||||
|
|
||||||
let e = self
|
let e = self
|
||||||
.load_elf_segment(
|
.load_elf_segment(
|
||||||
@ -601,7 +701,7 @@ impl BinaryLoader for ElfLoader {
|
|||||||
vaddr + load_bias,
|
vaddr + load_bias,
|
||||||
&elf_prot_flags,
|
&elf_prot_flags,
|
||||||
&elf_map_flags,
|
&elf_map_flags,
|
||||||
0,
|
total_size,
|
||||||
)
|
)
|
||||||
.map_err(|e| match e {
|
.map_err(|e| match e {
|
||||||
SystemError::EFAULT => ExecError::BadAddress(None),
|
SystemError::EFAULT => ExecError::BadAddress(None),
|
||||||
@ -618,7 +718,14 @@ impl BinaryLoader for ElfLoader {
|
|||||||
first_pt_load = false;
|
first_pt_load = false;
|
||||||
if elf_type == ElfType::DSO {
|
if elf_type == ElfType::DSO {
|
||||||
// todo: 在这里增加对load_bias和reloc_func_desc的更新代码
|
// todo: 在这里增加对load_bias和reloc_func_desc的更新代码
|
||||||
todo!()
|
load_bias += e.0.data()
|
||||||
|
- self
|
||||||
|
.elf_page_start(VirtAddr::new(
|
||||||
|
load_bias
|
||||||
|
+ TryInto::<usize>::try_into(seg_to_load.p_vaddr).unwrap(),
|
||||||
|
))
|
||||||
|
.data();
|
||||||
|
_reloc_func_desc = load_bias;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -714,7 +821,10 @@ impl BinaryLoader for ElfLoader {
|
|||||||
// kdebug!("elf_bss = {elf_bss:?}, elf_brk = {elf_brk:?}");
|
// kdebug!("elf_bss = {elf_bss:?}, elf_brk = {elf_brk:?}");
|
||||||
return Err(ExecError::BadAddress(Some(elf_bss)));
|
return Err(ExecError::BadAddress(Some(elf_bss)));
|
||||||
}
|
}
|
||||||
// todo: 动态链接:增加加载interpreter的代码
|
if interpreter.is_some() {
|
||||||
|
// TODO 添加对动态加载器的处理
|
||||||
|
// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#1249
|
||||||
|
}
|
||||||
// kdebug!("to create auxv");
|
// kdebug!("to create auxv");
|
||||||
|
|
||||||
self.create_auxv(param, program_entrypoint, phdr_vaddr, &ehdr)?;
|
self.create_auxv(param, program_entrypoint, phdr_vaddr, &ehdr)?;
|
||||||
|
@ -93,9 +93,8 @@ bitflags! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ExecParam<'a> {
|
pub struct ExecParam {
|
||||||
file_path: &'a str,
|
file: File,
|
||||||
file: Option<File>,
|
|
||||||
vm: Arc<AddressSpace>,
|
vm: Arc<AddressSpace>,
|
||||||
/// 一些标志位
|
/// 一些标志位
|
||||||
flags: ExecParamFlags,
|
flags: ExecParamFlags,
|
||||||
@ -112,19 +111,23 @@ pub enum ExecLoadMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
impl<'a> ExecParam<'a> {
|
impl ExecParam {
|
||||||
pub fn new(file_path: &'a str, vm: Arc<AddressSpace>, flags: ExecParamFlags) -> Self {
|
pub fn new(
|
||||||
Self {
|
file_path: &str,
|
||||||
file_path,
|
vm: Arc<AddressSpace>,
|
||||||
file: None,
|
flags: ExecParamFlags,
|
||||||
|
) -> Result<Self, SystemError> {
|
||||||
|
let inode = ROOT_INODE().lookup(file_path)?;
|
||||||
|
|
||||||
|
// 读取文件头部,用于判断文件类型
|
||||||
|
let file = File::new(inode, FileMode::O_RDONLY)?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
file,
|
||||||
vm,
|
vm,
|
||||||
flags,
|
flags,
|
||||||
init_info: ProcInitInfo::new(),
|
init_info: ProcInitInfo::new(),
|
||||||
}
|
})
|
||||||
}
|
|
||||||
|
|
||||||
pub fn file_path(&self) -> &'a str {
|
|
||||||
self.file_path
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vm(&self) -> &Arc<AddressSpace> {
|
pub fn vm(&self) -> &Arc<AddressSpace> {
|
||||||
@ -153,17 +156,13 @@ impl<'a> ExecParam<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn file_mut(&mut self) -> &mut File {
|
pub fn file_mut(&mut self) -> &mut File {
|
||||||
self.file.as_mut().unwrap()
|
&mut self.file
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ## 加载二进制文件
|
/// ## 加载二进制文件
|
||||||
pub fn load_binary_file(param: &mut ExecParam) -> Result<BinaryLoaderResult, SystemError> {
|
pub fn load_binary_file(param: &mut ExecParam) -> Result<BinaryLoaderResult, SystemError> {
|
||||||
let inode = ROOT_INODE().lookup(param.file_path)?;
|
|
||||||
|
|
||||||
// 读取文件头部,用于判断文件类型
|
// 读取文件头部,用于判断文件类型
|
||||||
let file = File::new(inode, FileMode::O_RDONLY)?;
|
|
||||||
param.file = Some(file);
|
|
||||||
let mut head_buf = [0u8; 512];
|
let mut head_buf = [0u8; 512];
|
||||||
param.file_mut().lseek(SeekFrom::SeekSet(0))?;
|
param.file_mut().lseek(SeekFrom::SeekSet(0))?;
|
||||||
let _bytes = param.file_mut().read(512, &mut head_buf)?;
|
let _bytes = param.file_mut().read(512, &mut head_buf)?;
|
||||||
|
@ -520,6 +520,8 @@ bitflags! {
|
|||||||
const SIGNALED = 1 << 6;
|
const SIGNALED = 1 << 6;
|
||||||
/// 进程需要迁移到其他cpu上
|
/// 进程需要迁移到其他cpu上
|
||||||
const NEED_MIGRATE = 1 << 7;
|
const NEED_MIGRATE = 1 << 7;
|
||||||
|
/// 随机化的虚拟地址空间,主要用于动态链接器的加载
|
||||||
|
const RANDOMIZE = 1 << 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user