Merge branch 'dlopen' into 'master'

Add support for dlopen(NULL, ...)

See merge request redox-os/relibc!315
This commit is contained in:
Jeremy Soller
2020-10-02 03:21:42 +00:00
7 changed files with 74 additions and 27 deletions
+20 -16
View File
@@ -40,10 +40,11 @@ pub unsafe extern "C" fn dlopen(cfilename: *const c_char, flags: c_int) -> *mut
//TODO support all sort of flags
let filename = if cfilename.is_null() {
ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
return ptr::null_mut();
None
} else {
str::from_utf8_unchecked(CStr::from_ptr(cfilename).to_bytes())
Some(str::from_utf8_unchecked(
CStr::from_ptr(cfilename).to_bytes(),
))
};
let tcb = match Tcb::current() {
@@ -60,31 +61,34 @@ pub unsafe extern "C" fn dlopen(cfilename: *const c_char, flags: c_int) -> *mut
return ptr::null_mut();
}
let mut linker = (&*tcb.linker_ptr).lock();
let cbs_c = linker.cbs.clone();
let cbs = cbs_c.borrow();
let id = match (cbs.load_library)(&mut linker, filename) {
Err(err) => {
eprintln!("dlopen: failed to load {}", filename);
eprintln!("dlopen: failed to load {:?}", filename);
ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
return ptr::null_mut();
}
Ok(id) => id,
};
if let Err(err) = (cbs.link)(&mut linker, None, None, Some(id)) {
(cbs.unload)(&mut linker, id);
eprintln!("dlopen: failed to link '{}': {}", filename, err);
ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
return ptr::null_mut();
};
if let Some(fname) = filename {
if let Err(err) = (cbs.link)(&mut linker, None, None, Some(id)) {
(cbs.unload)(&mut linker, id);
eprintln!("dlopen: failed to link '{}': {}", fname, err);
ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
return ptr::null_mut();
};
if let Err(err) = (cbs.run_init)(&mut linker, Some(id)) {
(cbs.unload)(&mut linker, id);
eprintln!("dlopen: failed to link '{}': {}", filename, err);
ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
return ptr::null_mut();
};
if let Err(err) = (cbs.run_init)(&mut linker, Some(id)) {
(cbs.unload)(&mut linker, id);
eprintln!("dlopen: failed to link '{}': {}", fname, err);
ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
return ptr::null_mut();
};
}
id as *mut c_void
}
+2 -2
View File
@@ -4,7 +4,7 @@ use goblin::error::Result;
pub struct LinkerCallbacks {
pub unload: Box<dyn Fn(&mut Linker, usize)>,
pub load_library: Box<dyn Fn(&mut Linker, &str) -> Result<usize>>,
pub load_library: Box<dyn Fn(&mut Linker, Option<&str>) -> Result<usize>>,
pub link:
Box<dyn Fn(&mut Linker, Option<&str>, Option<DSO>, Option<usize>) -> Result<Option<usize>>>,
pub get_sym: Box<dyn Fn(&Linker, &str, Option<usize>) -> Option<Symbol>>,
@@ -29,7 +29,7 @@ fn unload(linker: &mut Linker, libspace: usize) {
linker.unload(libspace)
}
fn load_library(linker: &mut Linker, name: &str) -> Result<usize> {
fn load_library(linker: &mut Linker, name: Option<&str>) -> Result<usize> {
linker.load_library(name)
}
+17 -9
View File
@@ -73,6 +73,8 @@ pub struct Linker {
pub cbs: Rc<RefCell<LinkerCallbacks>>,
}
const root_id: usize = 1;
impl Linker {
pub fn new(ld_library_path: Option<String>, verbose: bool) -> Self {
Self {
@@ -82,7 +84,7 @@ impl Linker {
verbose,
tls_index_offset: 0,
lib_spaces: BTreeMap::new(),
counter: 1,
counter: root_id + 1,
cbs: Rc::new(RefCell::new(LinkerCallbacks::new())),
}
}
@@ -175,13 +177,18 @@ impl Linker {
return Ok(deps);
}
pub fn load_library(&mut self, name: &str) -> Result<usize> {
let mut lib = Library::new();
self._load_library(name, &mut lib)?;
let ret = self.counter;
self.lib_spaces.insert(ret, lib);
self.counter += 1;
return Ok(ret);
pub fn load_library(&mut self, name: Option<&str>) -> Result<usize> {
match name {
Some(name) => {
let mut lib = Library::new();
self._load_library(name, &mut lib)?;
let ret = self.counter;
self.lib_spaces.insert(ret, lib);
self.counter += 1;
return Ok(ret);
}
None => return Ok(root_id),
}
}
fn _load_library(&mut self, name: &str, lib: &mut Library) -> Result<Option<DepTree>> {
if lib.objects.contains_key(name) || self.root.objects.contains_key(name) {
@@ -270,11 +277,11 @@ impl Linker {
pub fn get_sym(&self, name: &str, libspace: Option<usize>) -> Option<Symbol> {
match libspace {
None | Some(root_id) => self.root.get_sym(name),
Some(id) => {
let lib = self.lib_spaces.get(&id)?;
lib.get_sym(name)
}
None => self.root.get_sym(name),
}
}
@@ -290,6 +297,7 @@ impl Linker {
pub fn run_fini(&self, libspace: Option<usize>) -> Result<()> {
match libspace {
Some(root_id) => return Ok(()),
Some(id) => {
let lib = self.lib_spaces.get(&id).unwrap();
self.run_tree(&lib, &lib.dep_tree, ".fini_array")
+6
View File
@@ -127,6 +127,9 @@ STATIC_ONLY_NAMES+=\
unistd/getopt \
unistd/getopt_long \
DYNAMIC_ONLY_NAMES=\
dlfcn
# Binaries that may generate varied output
NAMES=\
$(EXPECT_NAMES) \
@@ -157,9 +160,11 @@ NAMES=\
BINS=$(patsubst %,bins_static/%,$(NAMES))
BINS+=$(patsubst %,bins_static/%,$(STATIC_ONLY_NAMES))
BINS+=$(patsubst %,bins_dynamic/%,$(NAMES))
BINS+=$(patsubst %,bins_dynamic/%,$(DYNAMIC_ONLY_NAMES))
EXPECT_BINS=$(patsubst %,bins_static/%,$(EXPECT_NAMES))
EXPECT_BINS+=$(patsubst %,bins_static/%,$(STATIC_ONLY_NAMES))
EXPECT_BINS+=$(patsubst %,bins_dynamic/%,$(EXPECT_NAMES))
EXPECT_BINS+=$(patsubst %,bins_dynamic/%,$(DYNAMIC_ONLY_NAMES))
TEST_RUNNER?=sh --
@@ -226,6 +231,7 @@ DYNAMIC_FLAGS=\
-Wl,-dynamic-linker=$(SYSROOT_LIB)/ld64.so.1 \
-Wl,--enable-new-dtags \
-Wl,-rpath=$(SYSROOT_LIB) \
-Wl,-export-dynamic \
-L $(SYSROOT_LIB) \
-lc
+28
View File
@@ -0,0 +1,28 @@
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int add(int a, int b)
{
return a + b;
}
int main()
{
void* handle = dlopen(NULL, RTLD_LAZY);
if (!handle) {
printf("dlopen(NULL) failed\n");
exit(1);
}
int (*f)(int, int) = dlsym(handle, "add");
if (!f) {
printf("dlsym(handle, add) failed\n");
exit(2);
}
int a = 22;
int b = 33;
printf("add(%d, %d) = %d\n", a, b, f(a, b));
}
View File
+1
View File
@@ -0,0 +1 @@
add(22, 33) = 55