1
0
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:
Chen 2019-06-13 21:46:13 +08:00 committed by GitHub
commit 6aded707c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 64 additions and 25 deletions

View File

@ -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;

View File

@ -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()