Merge branch 'tlssym' into 'master'
Fix dlsym of TLS variables See merge request redox-os/relibc!327
This commit is contained in:
@@ -358,12 +358,14 @@ impl DSO {
|
||||
base: mmap.as_ptr() as usize,
|
||||
value: sym.st_value as usize,
|
||||
size: sym.st_size as usize,
|
||||
sym_type: sym::st_type(sym.st_info),
|
||||
}
|
||||
} else {
|
||||
Symbol {
|
||||
base: 0,
|
||||
value: sym.st_value as usize,
|
||||
size: sym.st_size as usize,
|
||||
sym_type: sym::st_type(sym.st_info),
|
||||
}
|
||||
};
|
||||
} else {
|
||||
|
||||
+25
-4
@@ -6,14 +6,18 @@ use alloc::{
|
||||
};
|
||||
use core::{cell::RefCell, mem::transmute, ptr};
|
||||
use goblin::{
|
||||
elf::{program_header, reloc, Elf},
|
||||
elf::{program_header, reloc, sym::STT_TLS, Elf},
|
||||
error::{Error, Result},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
c_str::CString,
|
||||
fs::File,
|
||||
header::{fcntl, sys_mman, unistd::F_OK},
|
||||
header::{
|
||||
dl_tls::{__tls_get_addr, dl_tls_index},
|
||||
fcntl, sys_mman,
|
||||
unistd::F_OK,
|
||||
},
|
||||
io::Read,
|
||||
platform::types::c_void,
|
||||
};
|
||||
@@ -32,6 +36,7 @@ pub struct Symbol {
|
||||
pub value: usize,
|
||||
pub base: usize,
|
||||
pub size: usize,
|
||||
pub sym_type: u8,
|
||||
}
|
||||
|
||||
impl Symbol {
|
||||
@@ -91,8 +96,24 @@ impl Linker {
|
||||
|
||||
pub fn get_sym(&self, lib_id: usize, name: &str) -> Option<*mut c_void> {
|
||||
match self.objects.get(&lib_id) {
|
||||
Some(obj) => obj.get_sym(name).map(|s| s.as_ptr()),
|
||||
_ => None,
|
||||
Some(obj) => {
|
||||
return obj.get_sym(name).map(|s| {
|
||||
if s.sym_type != STT_TLS {
|
||||
s.as_ptr()
|
||||
} else {
|
||||
unsafe {
|
||||
let mut tls_index = dl_tls_index {
|
||||
ti_module: obj.tls_module_id as u64,
|
||||
ti_offset: s.value as u64,
|
||||
};
|
||||
__tls_get_addr(&mut tls_index)
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
_ => {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -40,7 +40,7 @@ pub struct Tcb {
|
||||
/// Size of the masters list in bytes (multiple of mem::size_of::<Master>())
|
||||
pub masters_len: usize,
|
||||
/// Index of last copied Master
|
||||
pub last_master_copied: usize,
|
||||
pub num_copied_masters: usize,
|
||||
/// Pointer to dynamic linker
|
||||
pub linker_ptr: *const Mutex<Linker>,
|
||||
/// pointer to rust memory allocator structure
|
||||
@@ -63,7 +63,7 @@ impl Tcb {
|
||||
tcb_len: tcb_page.len(),
|
||||
masters_ptr: ptr::null_mut(),
|
||||
masters_len: 0,
|
||||
last_master_copied: 0,
|
||||
num_copied_masters: 0,
|
||||
linker_ptr: ptr::null(),
|
||||
mspace: 0,
|
||||
},
|
||||
@@ -114,7 +114,7 @@ impl Tcb {
|
||||
if let Some(masters) = self.masters() {
|
||||
for (i, master) in masters
|
||||
.iter()
|
||||
.skip(self.last_master_copied)
|
||||
.skip(self.num_copied_masters)
|
||||
.filter(|m| m.len > 0)
|
||||
.enumerate()
|
||||
{
|
||||
@@ -135,7 +135,7 @@ impl Tcb {
|
||||
return Err(Error::Malformed(format!("failed to copy tls master {}", i)));
|
||||
}
|
||||
}
|
||||
self.last_master_copied = masters.len();
|
||||
self.num_copied_masters = masters.len();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -227,12 +227,23 @@ DYNAMIC_FLAGS+=\
|
||||
-lc
|
||||
|
||||
DEPS=../sysroot
|
||||
else
|
||||
DYNAMIC_FLAGS+=\
|
||||
-Wl,-rpath=\$$ORIGIN
|
||||
endif
|
||||
|
||||
bins_static/%: %.c $(DEPS)
|
||||
mkdir -p "$$(dirname "$@")"
|
||||
$(CC) "$<" -o "$@" $(FLAGS) $(STATIC_FLAGS)
|
||||
|
||||
bins_dynamic/%.so: %.c $(DEPS)
|
||||
mkdir -p "$$(dirname "$@")"
|
||||
$(CC) "$<" -o "$@" -shared -fpic $(FLAGS) $(DYNAMIC_FLAGS)
|
||||
|
||||
bins_dynamic/dlfcn: dlfcn.c bins_dynamic/sharedlib.so $(DEPS)
|
||||
mkdir -p "$$(dirname "$@")"
|
||||
$(CC) "$<" -o "$@" $(FLAGS) $(DYNAMIC_FLAGS)
|
||||
|
||||
bins_dynamic/%: %.c $(DEPS)
|
||||
mkdir -p "$$(dirname "$@")"
|
||||
$(CC) "$<" -o "$@" $(FLAGS) $(DYNAMIC_FLAGS)
|
||||
|
||||
+88
-14
@@ -5,24 +5,98 @@
|
||||
|
||||
int add(int a, int b)
|
||||
{
|
||||
return a + b;
|
||||
return a + b;
|
||||
}
|
||||
|
||||
void test_dlopen_null()
|
||||
{
|
||||
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));
|
||||
dlclose(handle);
|
||||
}
|
||||
|
||||
void test_dlopen_libc()
|
||||
{
|
||||
void* handle = dlopen("libc.so.6", RTLD_LAZY);
|
||||
if (!handle) {
|
||||
printf("dlopen(libc.so.6) failed\n");
|
||||
exit(1);
|
||||
}
|
||||
int (*f)(const char*) = dlsym(handle, "puts");
|
||||
if (!f) {
|
||||
printf("dlsym(handle, puts) failed\n");
|
||||
exit(2);
|
||||
}
|
||||
f("puts from dlopened libc");
|
||||
dlclose(handle);
|
||||
}
|
||||
|
||||
|
||||
void test_dlsym_function()
|
||||
{
|
||||
void* handle = dlopen("sharedlib.so", RTLD_LAZY);
|
||||
if (!handle) {
|
||||
printf("dlopen(sharedlib.so) failed\n");
|
||||
exit(1);
|
||||
}
|
||||
void (*f)() = dlsym(handle, "print");
|
||||
if (!f) {
|
||||
printf("dlsym(handle, print) failed\n");
|
||||
exit(2);
|
||||
}
|
||||
f();
|
||||
dlclose(handle);
|
||||
}
|
||||
|
||||
void test_dlsym_global_var()
|
||||
{
|
||||
void* handle = dlopen("sharedlib.so", RTLD_LAZY);
|
||||
if (!handle) {
|
||||
printf("dlopen(sharedlib.so) failed\n");
|
||||
exit(1);
|
||||
}
|
||||
int* global_var = dlsym(handle, "global_var");
|
||||
if (!global_var) {
|
||||
printf("dlsym(handle, global_var) failed\n");
|
||||
exit(2);
|
||||
}
|
||||
printf("main: global_var == %d\n", *global_var);
|
||||
dlclose(handle);
|
||||
}
|
||||
|
||||
void test_dlsym_tls_var()
|
||||
{
|
||||
void* handle = dlopen("sharedlib.so", RTLD_LAZY);
|
||||
if (!handle) {
|
||||
printf("dlopen(sharedlib.so) failed\n");
|
||||
exit(1);
|
||||
}
|
||||
int* tls_var = dlsym(handle, "tls_var");
|
||||
if (!tls_var) {
|
||||
printf("dlsym(handle, tls_var) failed\n");
|
||||
exit(2);
|
||||
}
|
||||
printf("main: tls_var == %d\n", *tls_var);
|
||||
dlclose(handle);
|
||||
}
|
||||
|
||||
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));
|
||||
test_dlopen_null();
|
||||
test_dlopen_libc();
|
||||
test_dlsym_function();
|
||||
test_dlsym_global_var();
|
||||
test_dlsym_tls_var();
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +1,6 @@
|
||||
add(22, 33) = 55
|
||||
puts from dlopened libc
|
||||
sharedlib: global_var == 42
|
||||
sharedlib: tls_var == 21
|
||||
main: global_var == 42
|
||||
main: tls_var == 21
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int global_var = 42;
|
||||
_Thread_local int tls_var = 21;
|
||||
|
||||
void print()
|
||||
{
|
||||
fprintf(stdout, "sharedlib: global_var == %d\n", global_var);
|
||||
fprintf(stdout, "sharedlib: tls_var == %d\n", tls_var);
|
||||
}
|
||||
Reference in New Issue
Block a user