Merge branch 'LD_LIBRARY_PATH' into 'master'

Ld library path

See merge request redox-os/relibc!279
This commit is contained in:
Jeremy Soller
2020-06-20 13:17:40 +00:00
3 changed files with 88 additions and 40 deletions
+53
View File
@@ -0,0 +1,53 @@
// Wrapper over the access syscall that doesn't touch errno variable,
// Do not use outside of ld_so
use crate::{c_str::CStr, platform::types::*};
#[cfg(target_os = "redox")]
use crate::header::unistd::{F_OK, R_OK, W_OK, X_OK};
#[cfg(target_os = "linux")]
pub unsafe fn access(path: *const c_char, mode: c_int) -> c_int {
let path = CStr::from_ptr(path);
syscall!(ACCESS, (path).as_ptr(), mode) as c_int
}
// Wrapper over the systemcall, Do not use outside of ld_so
#[cfg(target_os = "redox")]
pub unsafe fn access(path: *const c_char, mode: c_int) -> c_int {
let path = CStr::from_ptr(path).to_bytes();
let fd = match syscall::open(path, syscall::O_CLOEXEC) {
Ok(fd) => fd,
_ => return -1,
};
if mode == F_OK {
return 0;
}
let mut stat = syscall::Stat::default();
if syscall::fstat(fd, &mut stat).is_err() {
return -1;
}
let uid = match syscall::getuid() {
Ok(uid) => uid,
Err(_) => return -1,
};
let gid = match syscall::getgid() {
Ok(gid) => gid,
Err(_) => return -1,
};
let perms = if stat.st_uid as usize == uid {
stat.st_mode >> (3 * 2 & 0o7)
} else if stat.st_gid as usize == gid {
stat.st_mode >> (3 * 1 & 0o7)
} else {
stat.st_mode & 0o7
};
if (mode & R_OK == R_OK && perms & 0o4 != 0o4)
|| (mode & W_OK == W_OK && perms & 0o2 != 0o2)
|| (mode & X_OK == X_OK && perms & 0o1 != 0o1)
{
return -1;
}
0
}
+32 -39
View File
@@ -21,16 +21,16 @@ use crate::{
c_str::CString,
fs::File,
header::{fcntl, sys_mman, unistd},
io::{self, Read},
io::Read,
platform::types::c_void,
};
use super::{
access::access,
debug::{RTLDDebug, RTLDState, _dl_debug_state, _r_debug},
tcb::{Master, Tcb},
PAGE_SIZE,
};
#[cfg(target_os = "redox")]
const PATH_SEP: char = ';';
@@ -94,54 +94,41 @@ impl Linker {
}
pub fn load(&mut self, name: &str, path: &str) -> Result<()> {
self.dep_tree = self.load_recursive(name, path)?
.ok_or(Error::Malformed(format!(
"failed to find '{}'",
path
)))?;
self.dep_tree = self.load_recursive(name, path)?;
if self.verbose {
println!("Dep tree: {:#?}", self.dep_tree);
}
return Ok(());
}
fn load_recursive(&mut self, name: &str, path: &str) -> Result<Option<DepTree>> {
fn load_recursive(&mut self, name: &str, path: &str) -> Result<DepTree> {
if self.verbose {
println!("load {}: {}", name, path);
}
let path_c = CString::new(path)
.map_err(|err| Error::Malformed(format!("invalid path '{}': {}", path, err)))?;
let mut data = Vec::new();
{
let flags = fcntl::O_RDONLY | fcntl::O_CLOEXEC;
let mut file = match File::open(&path_c, flags) {
Ok(ok) => ok,
Err(err) => match err.kind() {
io::ErrorKind::NotFound => return Ok(None),
_ => return Err(Error::Malformed(format!("failed to open '{}': {}", path, err)))
}
};
file.read_to_end(&mut data)
.map_err(|err| Error::Malformed(format!("failed to read '{}': {}", path, err)))?;
}
if self.cir_dep.contains(name) {
return Err(Error::Malformed(format!(
"Circular dependency: {} is a dependency of itself",
name
)));
}
self.cir_dep.insert(name.to_string());
let mut deps = DepTree::new(name.to_string());
let mut data = Vec::new();
self.cir_dep.insert(name.to_string());
let path_c = CString::new(path)
.map_err(|err| Error::Malformed(format!("invalid path '{}': {}", path, err)))?;
{
let flags = fcntl::O_RDONLY | fcntl::O_CLOEXEC;
let mut file = File::open(&path_c, flags)
.map_err(|err| Error::Malformed(format!("failed to open '{}': {}", path, err)))?;
file.read_to_end(&mut data)
.map_err(|err| Error::Malformed(format!("failed to read '{}': {}", path, err)))?;
}
deps.deps = self.load_data(name, data.into_boxed_slice())?;
self.cir_dep.remove(name);
Ok(Some(deps))
Ok(deps)
}
pub fn load_data(&mut self, name: &str, data: Box<[u8]>) -> Result<Vec<DepTree>> {
@@ -164,12 +151,7 @@ impl Linker {
// It should be previously resolved so we don't need to worry about it
Ok(None)
} else if name.contains('/') {
Ok(Some(self.load_recursive(name, name)?
.ok_or(Error::Malformed(format!(
"failed to find '{}'",
name
)))?
))
Ok(Some(self.load_recursive(name, name)?))
} else {
let library_path = self.library_path.clone();
for part in library_path.split(PATH_SEP) {
@@ -181,8 +163,19 @@ impl Linker {
if self.verbose {
println!("check {}", path);
}
if let Some(deps) = self.load_recursive(name, &path)? {
return Ok(Some(deps));
let access = unsafe {
let path_c = CString::new(path.as_bytes()).map_err(|err| {
Error::Malformed(format!("invalid path '{}': {}", path, err))
})?;
// TODO: Use R_OK | X_OK
// We cannot use unix stdlib because errno is thead local variable
// and fs:[0] is not set yet.
access(path_c.as_ptr(), unistd::F_OK) == 0
};
if access {
return Ok(Some(self.load_recursive(name, &path)?));
}
}
+3 -1
View File
@@ -1,13 +1,15 @@
use goblin::elf::program_header::{self, program_header32, program_header64, ProgramHeader};
use self::tcb::{Master, Tcb};
use crate::{c_str::CStr, platform::types::*, start::Stack};
use crate::start::Stack;
pub const PAGE_SIZE: usize = 4096;
mod access;
pub mod debug;
pub mod linker;
pub mod start;
pub mod tcb;
pub fn static_init(sp: &'static Stack) {
let mut phdr_opt = None;
let mut phent_opt = None;