mirror of
https://github.com/rcore-os/rCore.git
synced 2024-11-22 16:16:16 +04:00
Merge pull request #59 from gjz010/shared-library
Shared library using auxv.
This commit is contained in:
commit
6aded707c4
@ -74,3 +74,5 @@ pub const AT_PHDR: u8 = 3;
|
||||
pub const AT_PHENT: u8 = 4;
|
||||
pub const AT_PHNUM: u8 = 5;
|
||||
pub const AT_PAGESZ: u8 = 6;
|
||||
pub const AT_BASE: u8 = 7;
|
||||
pub const AT_ENTRY: u8 = 9;
|
||||
|
@ -3,7 +3,7 @@ use core::fmt;
|
||||
|
||||
use core::str;
|
||||
use log::*;
|
||||
use rcore_memory::PAGE_SIZE;
|
||||
use rcore_memory::{PAGE_SIZE, Page};
|
||||
use rcore_thread::Tid;
|
||||
use spin::RwLock;
|
||||
use xmas_elf::{
|
||||
@ -174,22 +174,40 @@ impl Thread {
|
||||
_ => return Err("invalid ELF arch"),
|
||||
}
|
||||
|
||||
let mut auxv={
|
||||
let mut map = BTreeMap::new();
|
||||
if let Some(phdr_vaddr) = elf.get_phdr_vaddr() {
|
||||
map.insert(abi::AT_PHDR, phdr_vaddr as usize);
|
||||
}
|
||||
map.insert(abi::AT_PHENT, elf.header.pt2.ph_entry_size() as usize);
|
||||
map.insert(abi::AT_PHNUM, elf.header.pt2.ph_count() as usize);
|
||||
map.insert(abi::AT_PAGESZ, PAGE_SIZE);
|
||||
map
|
||||
};
|
||||
let mut entry_addr = elf.header.pt2.entry_point() as usize;
|
||||
// Make page table
|
||||
let (mut vm, bias) = elf.make_memory_set(inode);
|
||||
|
||||
// Check interpreter (for dynamic link)
|
||||
if let Ok(loader_path) = elf.get_interpreter() {
|
||||
info!("Handling interpreter... bias={:x}", bias);
|
||||
// assuming absolute path
|
||||
let inode = crate::fs::ROOT_INODE
|
||||
let interp_inode = crate::fs::ROOT_INODE
|
||||
.lookup_follow(loader_path, FOLLOW_MAX_DEPTH)
|
||||
.map_err(|_| "interpreter not found")?;
|
||||
// modify args for const_reloc
|
||||
args[0] = exec_path.into();
|
||||
args.insert(0, loader_path.into());
|
||||
// Elf const_reloc should not have INTERP
|
||||
// No infinite loop
|
||||
return Thread::new_user_vm(&inode, exec_path, args, envs);
|
||||
// load loader by bias and set aux vector.
|
||||
let mut interp_data: [u8; 0x3c0] = unsafe { MaybeUninit::uninitialized().into_initialized() };
|
||||
interp_inode
|
||||
.read_at(0, &mut interp_data)
|
||||
.map_err(|_| "failed to read from INode")?;
|
||||
let elf_interp=ElfFile::new(&interp_data)?;
|
||||
elf_interp.append_as_interpreter(&interp_inode, &mut vm, bias);
|
||||
info!("entry: {:x}", elf.header.pt2.entry_point() as usize);
|
||||
auxv.insert(abi::AT_ENTRY, elf.header.pt2.entry_point() as usize);
|
||||
auxv.insert(abi::AT_BASE, bias);
|
||||
entry_addr=elf_interp.header.pt2.entry_point() as usize + bias;
|
||||
}
|
||||
|
||||
// Make page table
|
||||
let mut vm = elf.make_memory_set(inode);
|
||||
|
||||
// User stack
|
||||
use crate::consts::{USER_STACK_OFFSET, USER_STACK_SIZE};
|
||||
@ -218,16 +236,7 @@ impl Thread {
|
||||
let init_info = ProcInitInfo {
|
||||
args,
|
||||
envs,
|
||||
auxv: {
|
||||
let mut map = BTreeMap::new();
|
||||
if let Some(phdr_vaddr) = elf.get_phdr_vaddr() {
|
||||
map.insert(abi::AT_PHDR, phdr_vaddr as usize);
|
||||
}
|
||||
map.insert(abi::AT_PHENT, elf.header.pt2.ph_entry_size() as usize);
|
||||
map.insert(abi::AT_PHNUM, elf.header.pt2.ph_count() as usize);
|
||||
map.insert(abi::AT_PAGESZ, PAGE_SIZE);
|
||||
map
|
||||
},
|
||||
auxv
|
||||
};
|
||||
unsafe {
|
||||
vm.with(|| ustack_top = init_info.push_at(ustack_top));
|
||||
@ -235,7 +244,7 @@ impl Thread {
|
||||
|
||||
trace!("{:#x?}", vm);
|
||||
|
||||
let entry_addr = elf.header.pt2.entry_point() as usize;
|
||||
|
||||
Ok((vm, entry_addr, ustack_top))
|
||||
}
|
||||
|
||||
@ -443,20 +452,24 @@ impl ToMemoryAttr for Flags {
|
||||
/// Helper functions to process ELF file
|
||||
trait ElfExt {
|
||||
/// Generate a MemorySet according to the ELF file.
|
||||
fn make_memory_set(&self, inode: &Arc<INode>) -> MemorySet;
|
||||
fn make_memory_set(&self, inode: &Arc<INode>) -> (MemorySet, usize);
|
||||
|
||||
/// Get interpreter string if it has.
|
||||
fn get_interpreter(&self) -> Result<&str, &str>;
|
||||
|
||||
/// Append current ELF file as interpreter into given memory set.
|
||||
/// This will insert the interpreter it a place which is "good enough" (since ld.so should be PIC).
|
||||
fn append_as_interpreter(&self, inode: &Arc<INode>, memory_set: &mut MemorySet, bias: usize);
|
||||
|
||||
/// Get virtual address of PHDR section if it has.
|
||||
fn get_phdr_vaddr(&self) -> Option<u64>;
|
||||
}
|
||||
|
||||
impl ElfExt for ElfFile<'_> {
|
||||
fn make_memory_set(&self, inode: &Arc<INode>) -> MemorySet {
|
||||
fn make_memory_set(&self, inode: &Arc<INode>) -> (MemorySet, usize) {
|
||||
debug!("creating MemorySet from ELF");
|
||||
let mut ms = MemorySet::new();
|
||||
|
||||
let mut farthest_memory:usize=0;
|
||||
for ph in self.program_iter() {
|
||||
if ph.get_type() != Ok(Type::Load) {
|
||||
continue;
|
||||
@ -474,10 +487,34 @@ impl ElfExt for ElfFile<'_> {
|
||||
},
|
||||
"elf",
|
||||
);
|
||||
if ph.virtual_addr() as usize+ph.mem_size() as usize > farthest_memory{
|
||||
farthest_memory=ph.virtual_addr() as usize+ph.mem_size() as usize;
|
||||
}
|
||||
}
|
||||
ms
|
||||
(ms, (Page::of_addr(farthest_memory+PAGE_SIZE)).start_address())
|
||||
}
|
||||
fn append_as_interpreter(&self, inode: &Arc<INode>, ms: &mut MemorySet, bias: usize){
|
||||
debug!("inserting interpreter from ELF");
|
||||
|
||||
for ph in self.program_iter(){
|
||||
if ph.get_type()!=Ok(Type::Load){
|
||||
continue;
|
||||
}
|
||||
ms.push(
|
||||
ph.virtual_addr() as usize +bias,
|
||||
ph.virtual_addr() as usize + ph.mem_size() as usize + bias,
|
||||
ph.flags().to_attr(),
|
||||
File{
|
||||
file: INodeForMap(inode.clone()),
|
||||
mem_start: ph.virtual_addr() as usize + bias,
|
||||
file_start: ph.offset() as usize,
|
||||
file_end: ph.offset() as usize+ph.file_size() as usize,
|
||||
allocator: GlobalFrameAlloc
|
||||
},
|
||||
"elf-interp"
|
||||
)
|
||||
}
|
||||
}
|
||||
fn get_interpreter(&self) -> Result<&str, &str> {
|
||||
let header = self
|
||||
.program_iter()
|
||||
|
Loading…
Reference in New Issue
Block a user