diff --git a/src/header/dlfcn/mod.rs b/src/header/dlfcn/mod.rs index d5b53db5fbcc35a90b386c77be4e85ff316d4fb6..cc10390c07e12800b2f2ce7a7a31d8fe969e7fee 100644 --- a/src/header/dlfcn/mod.rs +++ b/src/header/dlfcn/mod.rs @@ -108,9 +108,9 @@ pub unsafe extern "C" fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *m eprintln!("dlsym: linker_ptr: {:p}", tcb.linker_ptr); let linker = (&*tcb.linker_ptr).lock(); - if let Some(global) = linker.globals.get(symbol_str) { - eprintln!("dlsym({:p}, {}) = 0x{:x}", handle, symbol_str, *global); - *global as *mut c_void + if let Some(global) = linker.get_sym(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); diff --git a/src/header/unistd/mod.rs b/src/header/unistd/mod.rs index 3b15fd7e310f754d3014c1c5946cc5adcb97c558..449128ab43e4c7a1b1cc6c32b97ca7fca870af2b 100644 --- a/src/header/unistd/mod.rs +++ b/src/header/unistd/mod.rs @@ -5,7 +5,8 @@ use core::{convert::TryFrom, mem, ptr, slice}; use crate::{ c_str::CStr, header::{ - errno, fcntl, limits, stdlib::getenv, sys_ioctl, sys_time, sys_utsname, termios, time::timespec, + errno, fcntl, limits, stdlib::getenv, sys_ioctl, sys_time, sys_utsname, termios, + time::timespec, }, platform::{self, types::*, Pal, Sys}, }; diff --git a/src/ld_so/linker.rs b/src/ld_so/linker.rs index dd396112804631e507852a6dc9c6dc88daa8a11b..848645146058b9695a7493b6902ce18656904226 100644 --- a/src/ld_so/linker.rs +++ b/src/ld_so/linker.rs @@ -38,7 +38,9 @@ pub struct Linker { // Used by link /// Global symbols - pub globals: BTreeMap<String, usize>, + globals: BTreeMap<String, usize>, + /// Weak symbols + weak_syms: BTreeMap<String, usize>, /// Loaded library in-memory data mmaps: BTreeMap<String, &'static mut [u8]>, verbose: bool, @@ -51,6 +53,7 @@ impl Linker { library_path: library_path.to_string(), objects: BTreeMap::new(), globals: BTreeMap::new(), + weak_syms: BTreeMap::new(), mmaps: BTreeMap::new(), verbose, tls_index_offset: 0, @@ -129,6 +132,64 @@ impl Linker { } } + fn collect_syms( + elf: &Elf, + mmap: &[u8], + verbose: bool, + ) -> Result<(BTreeMap<String, usize>, BTreeMap<String, usize>)> { + let mut globals = BTreeMap::new(); + let mut weak_syms = BTreeMap::new(); + for sym in elf.dynsyms.iter() { + let bind = sym.st_bind(); + if sym.st_value == 0 || ![sym::STB_GLOBAL, sym::STB_WEAK].contains(&bind) { + continue; + } + let name: String; + let value: usize; + if let Some(name_res) = elf.dynstrtab.get(sym.st_name) { + name = name_res?.to_string(); + value = mmap.as_ptr() as usize + sym.st_value as usize; + } else { + continue; + } + match sym.st_bind() { + sym::STB_GLOBAL => { + if verbose { + println!(" global {}: {:x?} = {:#x}", &name, sym, value); + } + globals.insert(name, value); + } + sym::STB_WEAK => { + if verbose { + println!(" weak {}: {:x?} = {:#x}", &name, sym, value); + } + weak_syms.insert(name, value); + } + _ => unreachable!(), + } + } + return Ok((globals, weak_syms)); + } + + pub fn get_sym(&self, name: &str) -> Option<usize> { + if let Some(value) = self.globals.get(name) { + if self.verbose { + println!(" sym {} = {:#x}", name, value); + } + Some(*value) + } else if let Some(value) = self.weak_syms.get(name) { + if self.verbose { + println!(" sym {} = {:#x}", name, value); + } + Some(*value) + } else { + if self.verbose { + println!(" sym {} = undefined", name); + } + None + } + } + pub fn link(&mut self, primary_opt: Option<&str>) -> Result<Option<usize>> { let elfs = { let mut elfs = BTreeMap::new(); @@ -179,7 +240,7 @@ impl Linker { } } program_header::PT_TLS => { - if self.verbose{ + if self.verbose { println!(" load tls {:#x}: {:x?}", vsize, ph); } tls_size += vsize; @@ -221,18 +282,9 @@ impl Linker { if self.verbose { println!(" mmap {:p}, {:#x}", mmap.as_mut_ptr(), mmap.len()); } - // Locate all globals - for sym in elf.dynsyms.iter() { - if sym.st_bind() == sym::STB_GLOBAL && sym.st_value != 0 { - if let Some(name_res) = elf.dynstrtab.get(sym.st_name) { - let name = name_res?; - let value = mmap.as_ptr() as usize + sym.st_value as usize; - // println!(" global {}: {:x?} = {:#x}", name, sym, value); - self.globals.insert(name.to_string(), value); - } - } - } - + let (globals, weak_syms) = Linker::collect_syms(&elf, &mmap, self.verbose)?; + self.globals.extend(globals.into_iter()); + self.weak_syms.extend(weak_syms.into_iter()); self.mmaps.insert(elf_name.to_string(), mmap); } @@ -242,7 +294,7 @@ impl Linker { } else { None }; - if self.verbose{ + if self.verbose { println!("tcb {:x?}", tcb_opt); } // Copy data @@ -331,14 +383,20 @@ impl Linker { ); } if Some(*elf_name) == primary_opt { - tls_ranges.insert(elf_name.to_string(), (self.tls_index_offset, tcb_master.range())); + tls_ranges.insert( + elf_name.to_string(), + (self.tls_index_offset, tcb_master.range()), + ); tcb_masters[0] = tcb_master; } else { tcb_master.offset -= tls_offset; tls_offset += vsize; tls_ranges.insert( elf_name.to_string(), - (self.tls_index_offset + tcb_masters.len(), tcb_master.range()), + ( + self.tls_index_offset + tcb_masters.len(), + tcb_master.range(), + ), ); tcb_masters.push(tcb_master); } @@ -360,10 +418,6 @@ impl Linker { // Perform relocations, and protect pages for (elf_name, elf) in elfs.iter() { - let mmap = match self.mmaps.get_mut(*elf_name) { - Some(some) => some, - None => continue, - }; if self.verbose { println!("link {}", elf_name); } @@ -379,10 +433,6 @@ impl Linker { // rel // ); - let a = rel.r_addend.unwrap_or(0) as usize; - - let b = mmap.as_mut_ptr() as usize; - let s = if rel.r_sym > 0 { let sym = elf.dynsyms.get(rel.r_sym).ok_or(Error::Malformed(format!( "missing symbol for relocation {:?}", @@ -396,18 +446,20 @@ impl Linker { "missing name for symbol {:?}", sym )))??; - - if let Some(value) = self.globals.get(name) { - // println!(" sym {}: {:x?} = {:#x}", name, sym, value); - *value - } else { - // println!(" sym {}: {:x?} = undefined", name, sym); - 0 - } + self.get_sym(name).unwrap_or(0) } else { 0 }; + let a = rel.r_addend.unwrap_or(0) as usize; + + let mmap = match self.mmaps.get_mut(*elf_name) { + Some(some) => some, + None => continue, + }; + + let b = mmap.as_mut_ptr() as usize; + let (tm, t) = if let Some((tls_index, tls_range)) = tls_ranges.get(*elf_name) { (*tls_index, tls_range.start) } else { @@ -473,6 +525,10 @@ impl Linker { prot |= sys_mman::PROT_WRITE; } + let mmap = match self.mmaps.get_mut(*elf_name) { + Some(some) => some, + None => continue, + }; let res = unsafe { let ptr = mmap.as_mut_ptr().add(vaddr); if self.verbose { diff --git a/src/ld_so/tcb.rs b/src/ld_so/tcb.rs index 3b71ebfaadfe3ff381218c27d2166ee9dfd941c5..3a303088827e2e3b4d01dcb0bdac2131bb302b0f 100644 --- a/src/ld_so/tcb.rs +++ b/src/ld_so/tcb.rs @@ -2,11 +2,7 @@ use alloc::boxed::Box; use core::{mem, ops::Range, ptr, slice}; use goblin::error::{Error, Result}; -use crate::{ - header::sys_mman, - ld_so::linker::Linker, - sync::mutex::Mutex, -}; +use crate::{header::sys_mman, ld_so::linker::Linker, sync::mutex::Mutex}; use super::PAGE_SIZE; diff --git a/src/platform/redox/socket.rs b/src/platform/redox/socket.rs index 80eb515e8ba837b8404747d7d424c22220afac24..fd875c763513451529d8c06c8ba6a666cb78ebea 100644 --- a/src/platform/redox/socket.rs +++ b/src/platform/redox/socket.rs @@ -215,7 +215,7 @@ impl PalSocket for Sys { *error = 0; return 0; - }, + } _ => (), }, _ => (),