From 09aab1d96d516c91fe4fdfbb33925d7a15868c6c Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sat, 1 Jun 2019 10:10:25 +0200 Subject: [PATCH 1/2] Simplify code. --- src/wrapper/optional.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/wrapper/optional.rs b/src/wrapper/optional.rs index 6483872..3122fe7 100644 --- a/src/wrapper/optional.rs +++ b/src/wrapper/optional.rs @@ -77,15 +77,8 @@ where { let lib = Library::open(name)?; let api = Api::load(&lib)?; - let optional = match Optional::load(&lib) { - Ok(val) => Some(val), - Err(_) => None, - }; - Ok(Self { - lib: lib, - api: api, - optional: optional, - }) + let optional = Optional::load(&lib).ok(); + Ok(Self { lib, api, optional }) } ///Gives access to the optional API - constant version. pub fn optional(&self) -> &Option { From c267d1021d68b6ed5d2ca2fe284aad79c985a6f3 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sat, 1 Jun 2019 10:10:42 +0200 Subject: [PATCH 2/2] Add open_self/load_self functions. --- src/lib.rs | 1 + src/raw/common.rs | 15 +++++++++++++-- src/raw/unix.rs | 16 +++++++++++++++- src/raw/windows.rs | 12 +++++++++++- src/symbor/container.rs | 13 +++++++++++++ src/symbor/library.rs | 10 ++++++++++ src/wrapper/container.rs | 9 +++++++++ src/wrapper/optional.rs | 13 +++++++++++++ 8 files changed, 85 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index de4850e..6077926 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,6 +35,7 @@ I hope that this library will help you to quickly get what you need and avoid er | Overhead | Minimal | Minimal | **Some overhead** | | Low-level, unsafe API | Yes | Yes | Yes | | Object-oriented friendly | Yes | **No** | Yes | +| Load from the program itself | Yes | **No** | **No** | ## Safety diff --git a/src/raw/common.rs b/src/raw/common.rs index 585f60b..92dcd26 100644 --- a/src/raw/common.rs +++ b/src/raw/common.rs @@ -3,9 +3,9 @@ use std::ffi::{CStr, CString, OsStr}; //choose the right platform implementation here #[cfg(unix)] -use super::unix::{close_lib, get_sym, open_lib, Handle}; +use super::unix::{close_lib, get_sym, open_self, open_lib, Handle}; #[cfg(windows)] -use super::windows::{close_lib, get_sym, open_lib, Handle}; +use super::windows::{close_lib, get_sym, open_self, open_lib, Handle}; use std::mem::{size_of, transmute_copy}; @@ -64,6 +64,17 @@ impl Library { }) } /** + Open the main program itself as a library. + + This allows a shared library to load symbols of the program it was loaded + into. + */ + pub fn open_self() -> Result { + Ok(Self { + handle: unsafe { open_self() }?, + }) + } + /** Obtain symbol from opened library. **Note:** the `T` template type needs to have a size of a pointer. diff --git a/src/raw/unix.rs b/src/raw/unix.rs index 926e975..7e23db4 100644 --- a/src/raw/unix.rs +++ b/src/raw/unix.rs @@ -1,7 +1,7 @@ use super::super::err::Error; use std::ffi::{CStr, OsStr}; use libc::{c_int, c_void, dlclose, dlerror, dlopen, dlsym, RTLD_LAZY, RTLD_LOCAL}; -use std::ptr::null_mut; +use std::ptr::{null, null_mut}; use std::os::unix::ffi::OsStrExt; use std::io::{Error as IoError, ErrorKind}; @@ -36,6 +36,20 @@ pub unsafe fn get_sym(handle: Handle, name: &CStr) -> Result<*mut (), Error> { Ok(symbol as *mut ()) } +#[inline] +pub unsafe fn open_self() -> Result { + let _lock = DLERROR_MUTEX.lock(); + let handle = dlopen(null(), DEFAULT_FLAGS); + if handle.is_null() { + Err(Error::OpeningLibraryError(IoError::new( + ErrorKind::Other, + CStr::from_ptr(dlerror()).to_string_lossy().to_string(), + ))) + } else { + Ok(handle) + } +} + #[inline] pub unsafe fn open_lib(name: &OsStr) -> Result { let mut v: Vec = Vec::new(); diff --git a/src/raw/windows.rs b/src/raw/windows.rs index 7f4a8c7..f710b3f 100644 --- a/src/raw/windows.rs +++ b/src/raw/windows.rs @@ -4,7 +4,7 @@ use std::os::windows::ffi::OsStrExt; use std::sync::atomic::{AtomicBool, Ordering, ATOMIC_BOOL_INIT}; use std::io::{Error as IoError, ErrorKind}; use super::super::err::Error; -use std::ptr::null_mut; +use std::ptr::{null, null_mut}; use std::ffi::{CStr, OsStr}; use std::sync::Mutex; @@ -126,6 +126,16 @@ pub unsafe fn get_sym(handle: Handle, name: &CStr) -> Result<*mut (), Error> { } } +#[inline] +pub unsafe fn open_self() -> Result { + let mut handle: Handle = null_mut(); + if kernel32::GetModuleHandleExW(0, null(), &mut handle) == 0 { + Err(Error::OpeningLibraryError(get_win_error())) + } else { + Ok(handle) + } +} + #[inline] pub unsafe fn open_lib(name: &OsStr) -> Result { let wide_name: Vec = name.encode_wide().chain(Some(0)).collect(); diff --git a/src/symbor/container.rs b/src/symbor/container.rs index d2fecfd..d902631 100644 --- a/src/symbor/container.rs +++ b/src/symbor/container.rs @@ -62,6 +62,19 @@ where let api = T::load(static_ref)?; Ok(Self { api: api, lib: lib }) } + ///Load all symbols from the program itself. + /// + /// This allows a shared library to load symbols of the program it was + /// loaded into. + pub unsafe fn load_self() -> Result { + let lib = Library::open_self()?; + //this is cheating of course + //but it is safe because Library and api is placed in the same structure + //and therefore it is released at the same time. + let static_ref: &'static Library = transmute(&lib); + let api = T::load(static_ref)?; + Ok(Self { api: api, lib: lib }) + } } impl Deref for Container diff --git a/src/symbor/library.rs b/src/symbor/library.rs index 6bbd3b2..f2e704c 100644 --- a/src/symbor/library.rs +++ b/src/symbor/library.rs @@ -55,6 +55,16 @@ impl Library { }) } + /// Open the program itself as library. + /// + /// This allows a shared library to load symbols of the program it was + /// loaded into. + pub fn open_self() -> Result { + Ok(Library { + lib: RawLib::open_self()?, + }) + } + /// Obtain a symbol from library. /// /// This method is the most general one and allows obtaining basically everything assuming diff --git a/src/wrapper/container.rs b/src/wrapper/container.rs index 2f4f47b..fe625a1 100644 --- a/src/wrapper/container.rs +++ b/src/wrapper/container.rs @@ -69,6 +69,15 @@ where let api = T::load(&lib)?; Ok(Self { lib: lib, api: api }) } + ///Load all symbols from the program itself. + /// + /// This allows a shared library to load symbols of the program it was + /// loaded into. + pub unsafe fn load_self() -> Result, Error> { + let lib = Library::open_self()?; + let api = T::load(&lib)?; + Ok(Self { lib: lib, api: api }) + } } impl Deref for Container diff --git a/src/wrapper/optional.rs b/src/wrapper/optional.rs index 3122fe7..a3a6dc1 100644 --- a/src/wrapper/optional.rs +++ b/src/wrapper/optional.rs @@ -80,6 +80,19 @@ where let optional = Optional::load(&lib).ok(); Ok(Self { lib, api, optional }) } + + ///Load all symbols (including optional if it is possible) from the + ///program itself. + /// + /// This allows a shared library to load symbols of the program it was + /// loaded into. + pub unsafe fn load_self() -> Result, Error> { + let lib = Library::open_self()?; + let api = Api::load(&lib)?; + let optional = Optional::load(&lib).ok(); + Ok(Self { lib, api, optional }) + } + ///Gives access to the optional API - constant version. pub fn optional(&self) -> &Option { return &self.optional;