Browse Source

WIP - implementation of dlfcn

Jeremy Soller 5 years ago
parent
commit
a3f7a174f6
2 changed files with 82 additions and 18 deletions
  1. 66 10
      src/header/dlfcn/mod.rs
  2. 16 8
      src/ld_so/linker.rs

+ 66 - 10
src/header/dlfcn/mod.rs

@@ -5,7 +5,7 @@ use core::{
     sync::atomic::{AtomicUsize, Ordering},
 };
 
-use crate::{c_str::CStr, platform::types::*};
+use crate::{c_str::CStr, ld_so::tcb::Tcb, platform::types::*};
 
 pub const RTLD_LAZY: c_int = 0x0001;
 pub const RTLD_NOW: c_int = 0x0002;
@@ -47,8 +47,41 @@ pub unsafe extern "C" fn dlopen(filename: *const c_char, flags: c_int) -> *mut c
     eprintln!("dlopen({:?}, {:#>04x})", filename_opt, flags);
 
     if let Some(filename) = filename_opt {
-        ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
-        ptr::null_mut()
+        if let Some(tcb) = Tcb::current() {
+            if tcb.linker_ptr.is_null() {
+                eprintln!("dlopen: linker not found");
+                ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
+                return ptr::null_mut();
+            }
+
+            eprintln!("dlopen: linker_ptr: {:p}", tcb.linker_ptr);
+            let mut linker = (&*tcb.linker_ptr).lock();
+
+            match linker.load_library(filename) {
+                Ok(()) => (),
+                Err(err) => {
+                    eprintln!("dlopen: failed to load {}", filename);
+                    ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
+                    return ptr::null_mut();
+                }
+            }
+
+            match linker.link(None) {
+                Ok(ok) => (),
+                Err(err) => {
+                    eprintln!("dlopen: failed to link '{}': {}", filename, err);
+                    ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
+                    return ptr::null_mut();
+                }
+            };
+
+            // TODO
+            1 as *mut c_void
+        } else {
+            eprintln!("dlopen: tcb not found");
+            ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
+            ptr::null_mut()
+        }
     } else {
         1 as *mut c_void
     }
@@ -56,15 +89,38 @@ pub unsafe extern "C" fn dlopen(filename: *const c_char, flags: c_int) -> *mut c
 
 #[no_mangle]
 pub unsafe extern "C" fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void {
-    let symbol_opt = if symbol.is_null() {
-        None
-    } else {
-        Some(str::from_utf8_unchecked(CStr::from_ptr(symbol).to_bytes()))
-    };
+    if symbol.is_null() {
+        ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
+        return ptr::null_mut();
+    }
+
+    let symbol_str = str::from_utf8_unchecked(CStr::from_ptr(symbol).to_bytes());
+
+    eprintln!("dlsym({:p}, {})", handle, symbol_str);
+
+    if let Some(tcb) = Tcb::current() {
+        if tcb.linker_ptr.is_null() {
+            eprintln!("dlopen: linker not found");
+            ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
+            return ptr::null_mut();
+        }
 
-    eprintln!("dlsym({:p}, {:?})", handle, symbol_opt);
+        eprintln!("dlsym: linker_ptr: {:p}", tcb.linker_ptr);
+        let linker = (&*tcb.linker_ptr).lock();
 
-    ptr::null_mut()
+        if let Some(global) = linker.globals.get(symbol_str) {
+            eprintln!("dlsym({:p}, {}) = 0x{:x}", handle, symbol_str, *global);
+            *global as *mut c_void
+        } else {
+            eprintln!("dlsym: symbol not found");
+            ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
+            ptr::null_mut()
+        }
+    } else {
+        eprintln!("dlsym: tcb not found");
+        ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
+        ptr::null_mut()
+    }
 }
 
 #[no_mangle]

+ 16 - 8
src/ld_so/linker.rs

@@ -38,7 +38,7 @@ pub struct Linker {
 
     // Used by link
     /// Global symbols
-    globals: BTreeMap<String, usize>,
+    pub globals: BTreeMap<String, usize>,
     /// Loaded library in-memory data
     mmaps: BTreeMap<String, &'static mut [u8]>,
 }
@@ -226,8 +226,12 @@ impl Linker {
         }
 
         // Allocate TLS
-        let tcb = unsafe { Tcb::new(tls_size)? };
-        println!("tcb {:x?}", tcb);
+        let mut tcb_opt = if primary_opt.is_some() {
+            Some(unsafe { Tcb::new(tls_size)? })
+        } else {
+            None
+        };
+        println!("tcb {:x?}", tcb_opt);
 
         // Copy data
         let mut tls_offset = tls_primary;
@@ -333,9 +337,11 @@ impl Linker {
         }
 
         // Set master images for TLS and copy TLS data
-        unsafe {
-            tcb.set_masters(tcb_masters.into_boxed_slice());
-            tcb.copy_masters()?;
+        if let Some(ref mut tcb) = tcb_opt {
+            unsafe {
+                tcb.set_masters(tcb_masters.into_boxed_slice());
+                tcb.copy_masters()?;
+            }
         }
 
         // Perform relocations, and protect pages
@@ -468,8 +474,10 @@ impl Linker {
         }
 
         // Activate TLS
-        unsafe {
-            tcb.activate();
+        if let Some(ref mut tcb) = tcb_opt {
+            unsafe {
+                tcb.activate();
+            }
         }
 
         // Perform indirect relocations (necessary evil), gather entry point