Skip to content

Commit

Permalink
Merge pull request #19 from dronesforwork-forks/load-self
Browse files Browse the repository at this point in the history
Add functions for loading symbols from the program itself
  • Loading branch information
szymonwieloch authored Jun 1, 2019
2 parents 41ac766 + c267d10 commit 9c633b5
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 13 deletions.
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 13 additions & 2 deletions src/raw/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -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<Library, Error> {
Ok(Self {
handle: unsafe { open_self() }?,
})
}
/**
Obtain symbol from opened library.
**Note:** the `T` template type needs to have a size of a pointer.
Expand Down
16 changes: 15 additions & 1 deletion src/raw/unix.rs
Original file line number Diff line number Diff line change
@@ -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};

Expand Down Expand Up @@ -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<Handle, Error> {
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<Handle, Error> {
let mut v: Vec<u8> = Vec::new();
Expand Down
12 changes: 11 additions & 1 deletion src/raw/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -126,6 +126,16 @@ pub unsafe fn get_sym(handle: Handle, name: &CStr) -> Result<*mut (), Error> {
}
}

#[inline]
pub unsafe fn open_self() -> Result<Handle, Error> {
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<Handle, Error> {
let wide_name: Vec<u16> = name.encode_wide().chain(Some(0)).collect();
Expand Down
13 changes: 13 additions & 0 deletions src/symbor/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Self, Error> {
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<T> Deref for Container<T>
Expand Down
10 changes: 10 additions & 0 deletions src/symbor/library.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Library, Error> {
Ok(Library {
lib: RawLib::open_self()?,
})
}

/// Obtain a symbol from library.
///
/// This method is the most general one and allows obtaining basically everything assuming
Expand Down
9 changes: 9 additions & 0 deletions src/wrapper/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Container<T>, Error> {
let lib = Library::open_self()?;
let api = T::load(&lib)?;
Ok(Self { lib: lib, api: api })
}
}

impl<T> Deref for Container<T>
Expand Down
24 changes: 15 additions & 9 deletions src/wrapper/optional.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,22 @@ 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 })
}

///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<OptionalContainer<Api, Optional>, 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<Optional> {
return &self.optional;
Expand Down

0 comments on commit 9c633b5

Please sign in to comment.