Merge branch 'dlopen' into 'master'
Add support for dlopen(NULL, ...) See merge request redox-os/relibc!315
This commit is contained in:
+20
-16
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
add(22, 33) = 55
|
||||
Reference in New Issue
Block a user