Merge branch 'use_kernel_loaded_elf' into 'master'
Use Kernel mapped binaries when available. See merge request redox-os/relibc!262
This commit is contained in:
@@ -66,7 +66,7 @@ pub unsafe extern "C" fn dlopen(filename: *const c_char, flags: c_int) -> *mut c
|
||||
}
|
||||
}
|
||||
|
||||
match linker.link(None) {
|
||||
match linker.link(None, None) {
|
||||
Ok(ok) => (),
|
||||
Err(err) => {
|
||||
eprintln!("dlopen: failed to link '{}': {}", filename, err);
|
||||
|
||||
+53
-16
@@ -29,6 +29,12 @@ const PATH_SEP: char = ';';
|
||||
#[cfg(target_os = "linux")]
|
||||
const PATH_SEP: char = ':';
|
||||
|
||||
pub struct DSO {
|
||||
pub name: String,
|
||||
pub base_addr: usize,
|
||||
pub entry_point: usize,
|
||||
}
|
||||
|
||||
pub struct Linker {
|
||||
// Used by load
|
||||
/// Library path to search when loading library by name
|
||||
@@ -190,7 +196,7 @@ impl Linker {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn link(&mut self, primary_opt: Option<&str>) -> Result<Option<usize>> {
|
||||
pub fn link(&mut self, primary_opt: Option<&str>, dso: Option<DSO>) -> Result<Option<usize>> {
|
||||
let elfs = {
|
||||
let mut elfs = BTreeMap::new();
|
||||
for (name, data) in self.objects.iter() {
|
||||
@@ -262,22 +268,41 @@ impl Linker {
|
||||
// Allocate memory
|
||||
let mmap = unsafe {
|
||||
let size = bounds.1 /* - bounds.0 */;
|
||||
let ptr = sys_mman::mmap(
|
||||
ptr::null_mut(),
|
||||
size,
|
||||
//TODO: Make it possible to not specify PROT_EXEC on Redox
|
||||
sys_mman::PROT_READ | sys_mman::PROT_WRITE,
|
||||
sys_mman::MAP_ANONYMOUS | sys_mman::MAP_PRIVATE,
|
||||
-1,
|
||||
0,
|
||||
);
|
||||
if ptr as usize == !0
|
||||
/* MAP_FAILED */
|
||||
{
|
||||
return Err(Error::Malformed(format!("failed to map {}", elf_name)));
|
||||
let same_elf = if let Some(prog) = dso.as_ref() {
|
||||
if prog.name == *elf_name {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
};
|
||||
if same_elf {
|
||||
let addr = dso.as_ref().unwrap().base_addr;
|
||||
sys_mman::mprotect(
|
||||
addr as *mut c_void,
|
||||
size,
|
||||
sys_mman::PROT_READ | sys_mman::PROT_WRITE,
|
||||
);
|
||||
slice::from_raw_parts_mut(addr as *mut u8, size)
|
||||
} else {
|
||||
let ptr = sys_mman::mmap(
|
||||
ptr::null_mut(),
|
||||
size,
|
||||
//TODO: Make it possible to not specify PROT_EXEC on Redox
|
||||
sys_mman::PROT_READ | sys_mman::PROT_WRITE,
|
||||
sys_mman::MAP_ANONYMOUS | sys_mman::MAP_PRIVATE,
|
||||
-1,
|
||||
0,
|
||||
);
|
||||
if ptr as usize == !0
|
||||
/* MAP_FAILED */
|
||||
{
|
||||
return Err(Error::Malformed(format!("failed to map {}", elf_name)));
|
||||
}
|
||||
ptr::write_bytes(ptr as *mut u8, 0, size);
|
||||
slice::from_raw_parts_mut(ptr as *mut u8, size)
|
||||
}
|
||||
ptr::write_bytes(ptr as *mut u8, 0, size);
|
||||
slice::from_raw_parts_mut(ptr as *mut u8, size)
|
||||
};
|
||||
if self.verbose {
|
||||
println!(" mmap {:p}, {:#x}", mmap.as_mut_ptr(), mmap.len());
|
||||
@@ -308,6 +333,18 @@ impl Linker {
|
||||
});
|
||||
let mut tls_ranges = BTreeMap::new();
|
||||
for (elf_name, elf) in elfs.iter() {
|
||||
let same_elf = if let Some(prog) = dso.as_ref() {
|
||||
if prog.name == *elf_name {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
};
|
||||
if same_elf {
|
||||
continue;
|
||||
}
|
||||
let object = match self.objects.get(*elf_name) {
|
||||
Some(some) => some,
|
||||
None => continue,
|
||||
|
||||
+26
-4
@@ -6,8 +6,11 @@ use crate::{
|
||||
c_str::CStr, header::unistd, platform::types::c_char, start::Stack, sync::mutex::Mutex,
|
||||
};
|
||||
|
||||
use super::{linker::Linker, tcb::Tcb};
|
||||
use crate::header::sys_auxv::AT_ENTRY;
|
||||
use super::{
|
||||
linker::{Linker, DSO},
|
||||
tcb::Tcb,
|
||||
};
|
||||
use crate::header::sys_auxv::{AT_ENTRY, AT_PHDR};
|
||||
|
||||
unsafe fn get_argv(mut ptr: *const usize) -> (Vec<String>, *const usize) {
|
||||
//traverse the stack and collect argument vector
|
||||
@@ -149,7 +152,26 @@ pub extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: usize) ->
|
||||
} else {
|
||||
&argv[0]
|
||||
};
|
||||
|
||||
// if we are not running in manual mode, then the main
|
||||
// program is already loaded by the kernel and we want
|
||||
// to use it.
|
||||
let program = {
|
||||
let mut pr = None;
|
||||
if !is_manual {
|
||||
let phdr = *auxv.get(&AT_PHDR).unwrap();
|
||||
if phdr != 0 {
|
||||
let p = DSO {
|
||||
name: path.to_owned(),
|
||||
entry_point: *auxv.get(&AT_ENTRY).unwrap(),
|
||||
// The 0x40 is the size of Elf header not a good idea for different bit size
|
||||
// compatiablility but it will always work on 64 bit systems,
|
||||
base_addr: phdr - 0x40,
|
||||
};
|
||||
pr = Some(p);
|
||||
}
|
||||
}
|
||||
pr
|
||||
};
|
||||
let mut linker = Linker::new(library_path, false);
|
||||
match linker.load(&path, &path) {
|
||||
Ok(()) => (),
|
||||
@@ -160,7 +182,7 @@ pub extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: usize) ->
|
||||
}
|
||||
}
|
||||
|
||||
let entry = match linker.link(Some(&path)) {
|
||||
let entry = match linker.link(Some(&path), program) {
|
||||
Ok(ok) => match ok {
|
||||
Some(some) => some,
|
||||
None => {
|
||||
|
||||
Reference in New Issue
Block a user