GithubHelp home page GithubHelp logo

tyleo / sharedlib Goto Github PK

View Code? Open in Web Editor NEW

This project forked from nagisa/rust_libloading

31.0 31.0 5.0 11.52 MB

A cross-platform shared library loader.

Home Page: https://tyleo.github.io/sharedlib/

License: ISC License

Rust 100.00%

sharedlib's People

Contributors

adamcrume avatar ktff avatar lilianmoraru avatar llogiq avatar mbrubeck avatar nagisa avatar skade avatar tyleo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

sharedlib's Issues

Send

Is it possible to make any of the Lib structs safely implement Send trait ?

Add tests which compile, load, and run code from a separate project

I would like to have tests which load a freshly compiled shared library. I have an msbuild project which does this but I would like to convert it into gradle. Since the whole point of this code is to be able to load your own compiled shared libraries, we should have at least one test which does exactly that.

Typing functions at runtime or calling untyped functions

Since I want to load dynamic libraries manually at runtime, I might also first know about the function types at runtime, so doing it like in the example code, where you cast the functions found by a name functions to a specific function type, won't work.
Specifically, I'm working on a scripting language, and want to add support for calling extern functions. This would be the best way to call it.
What I basically want is something method, which takes the name and the byte representations of arguments, and returns the byte representation of the return value.
Is something like this possible as well?
This might also help for calling variadic functions like printf, where I don't know a real dynamic way yet.

Cannot open library by its absolute path if it's not canonicalized

I am facing strange behavior: when I am passing the absolute path to Lib::new method, it returns an error saying that it cannot find the file. However, calling canonicalize on the passed Path removes the problem. I wouldn't call it weird if the original path wouldn't be absolute, but it is

I've used this code to check if my suspicions are correct. I've used sharedlib and libloading crates as alternatives. The second test passes, and the first one fails on the third assert

use sharedlib::Lib;
use libloading::Library;
use std::path::Path;

static LIB_PATH: &str = "/tmp/libgetset.so";

#[test]
fn test_not_canonical_path() {
    let path = Path::new(LIB_PATH);

    println!("{:?}", &path);
    assert!(path.exists());

    let library = unsafe { Library::new(&path) };
    assert!(library.is_ok());

    let library = unsafe { Lib::new(&path) };
    assert!(library.is_ok());
}

#[test]
fn test_canonical_path() {
    let path = Path::new(LIB_PATH).canonicalize().unwrap();
    
    println!("{:?}", &path);
    assert!(path.exists());

    let library = unsafe { Library::new(&path) };
    assert!(library.is_ok());

    let library = unsafe { Lib::new(&path) };
    assert!(library.is_ok());
}

fn main() {
}

I am using Linux machine with Ubuntu 16.04

The dynamic library I am using is compiled getset procedural macro, but I think it doesn't really matter and you can replace it with what you have at hand

[Question] Memory requirement for loading a "dylib"

I was trying to hack around dlopen and then I found sharedlib. Looks like I finally found an answer to developing a plugin system for my application :-) So, first of all, thanks!

My requirement is kind of a classic use case for sharedlib. My application will have multiple layers (protocols and APIs) of plugins, with the eventual goal of making these plugins composable. These plugins need to be loaded at runtime by the main binary (named unicorn), depending on runtime arguments and configuration.

The core application is written in Rust and, for now, all the plugins will be in Rust as well. I'm compiling them using crate_type as dylib. Each of these plugins expose a set of known symbols. They are stored in a known location, like this:

- plugins/
    -- libx.so
    -- liby.so

To make things simple, consider this example: When the main binary is run with unicorn run x, it loads libx with Lib::new("plugins/libx.so"), tries to find a function symbol called run\0 and executes it.

Now, my question is, pardon the noobness: Will sharedlib load the entire .so file in memory when I try to load one of the plugins? So, if the .so file is 5MB in size, does that mean 5MB of memory is used to open the lib?

(Edit) P.S. AFAIK Dynamic loading is supposed to load the library in memory, get pointers, execute them and unload. My question is to know whether sharedlib does the same for the libraries it loads.

add example/test for placing Lib and a Func in a struct

I can't figure out the lifetimes. As far as I can tell, this should be valid:

use winapi::{HANDLE, DWORD, PCHAR, BOOL};

use winapi::{HMODULE, FARPROC};
use kernel32::{LoadLibraryA, FreeLibrary};
use sharedlib::{Lib, Func, Symbol, Result};

static path: &'static str = "winsta.dll\0";
type connect_a = extern "system" fn (hServer: HANDLE, SessionID: DWORD, TargetSessionID: DWORD, pPassword: *const u8, bWait: BOOL) -> BOOL;

pub struct Dll<'a> {
    lib: Lib,
    connect_a: Func<'a, connect_a>,
}
impl<'a> Dll<'a> {
    pub fn WinStationConnectA(&self, h: HANDLE, sid: DWORD, tsid: DWORD, pw: *const u8, wait: BOOL) -> BOOL {
        unsafe {
            self.connect_a.get()(h, sid, tsid, pw, wait)
        }
    }
}

pub fn load<'a>() -> Result<Dll<'a>> {
    let lib0: Lib = try!(unsafe {Lib::new(path)} );
    let sym = try!(unsafe {lib0.find_func("WinStationConnectA\0")});
    let dll: Dll<'a> = Dll {
        lib: lib0,
        connect_a: sym,
    };
    return Ok(dll)
}

It should be possible to put a Lib and a Func into a struct that's parameterized by a lifetime, since the Lib will outlive the Func. But the compiler claims that lib0 only lives until the end of the function, even though I move it into .lib. Clearly I intend it to live as long as the Dll struct lives, but I see the problem that interior mutability in Dll could result in assignment to .lib.

I imagine this use case isn't unique, and I couldn't find any examples in the documentation showing the correct way to do this.

cargo test fails on macOS

Interested in using this project but when I ran the tests I got failures, please advise:

thread 'test::shared::check_test_value' panicked at 'called `Result::unwrap()` on an `Err` value: Error(LibraryOpen("test/.build/libexamplelib.dylib"), State { next_error: Some(Error(OsError("dlopen(test/.build/libexamplelib.dylibassertion failed: `(left == right)`\n  left: ``,\n right: ``, 1): image not found", "dlopen"), State { next_error: None })) })', libcore/result.rs:945:5

---- test::shared::create_struct_unsafe stdout ----
thread 'test::shared::create_struct_unsafe' panicked at 'called `Result::unwrap()` on an `Err` value: Error(LibraryOpen("test/.build/libexamplelib.dylib"), State { next_error: Some(Error(OsError("dlopen(test/.build/libexamplelib.dylibassertion failed: `(left == right)`\n  left: ``,\n right: ``, 1): image not found", "dlopen"), State { next_error: None })) })', libcore/result.rs:945:5
note: Run with `RUST_BACKTRACE=1` for a backtrace.

---- test::shared::add_2_numbers stdout ----
thread 'test::shared::add_2_numbers' panicked at 'called `Result::unwrap()` on an `Err` value: Error(LibraryOpen("test/.build/libexamplelib.dylib"), State { next_error: Some(Error(OsError("dlopen(test/.build/libexamplelib.dylibassertion failed: `(left == right)`\n  left: ``,\n right: ``, 1): image not found", "dlopen"), State { next_error: None })) })', libcore/result.rs:945:5

---- test::shared::create_struct_arc stdout ----
thread 'test::shared::create_struct_arc' panicked at 'called `Result::unwrap()` on an `Err` value: Error(LibraryOpen("test/.build/libexamplelib.dylib"), State { next_error: Some(Error(OsError("dlopen(test/.build/libexamplelib.dylibassertion failed: `(left == right)`\n  left: ``,\n right: ``, 1): image not found", "dlopen"), State { next_error: None })) })', libcore/result.rs:945:5

---- test::shared::create_struct_safe stdout ----
thread 'test::shared::create_struct_safe' panicked at 'called `Result::unwrap()` on an `Err` value: Error(LibraryOpen("test/.build/libexamplelib.dylib"), State { next_error: Some(Error(OsError("dlopen(test/.build/libexamplelib.dylibassertion failed: `(left == right)`\n  left: ``,\n right: ``, 1): image not found", "dlopen"), State { next_error: None })) })', libcore/result.rs:945:5

---- test::shared::load_examplelib stdout ----
thread 'test::shared::load_examplelib' panicked at 'called `Result::unwrap()` on an `Err` value: Error(LibraryOpen("test/.build/libexamplelib.dylib"), State { next_error: Some(Error(OsError("dlopen(test/.build/libexamplelib.dylibassertion failed: `(left == right)`\n  left: ``,\n right: ``, 1): image not found", "dlopen"), State { next_error: None })) })', libcore/result.rs:945:5

---- test::unix::shared::libm_ceil stdout ----
thread 'test::unix::shared::libm_ceil' panicked at 'called `Result::unwrap()` on an `Err` value: Error(LibraryOpen("libm.dylib"), State { next_error: Some(Error(OsError("dlopen(libm.dylibmassertion failed: `(left == right)`\n  left: ``,\n right: ``, 1): image not found", "dlopen"), State { next_error: None })) })', libcore/result.rs:945:5

---- test::unix::shared::new_libm stdout ----
thread 'test::unix::shared::new_libm' panicked at 'called `Result::unwrap()` on an `Err` value: Error(LibraryOpen("libm.dylib"), State { next_error: Some(Error(OsError("dlopen(libm.dylibmassertion failed: `(left == right)`\n  left: ``,\n right: ``, 1): image not found", "dlopen"), State { next_error: None })) })', libcore/result.rs:945:5

---- test::unix::shared::libm_ceil0 stdout ----
thread 'test::unix::shared::libm_ceil0' panicked at 'called `Result::unwrap()` on an `Err` value: Error(LibraryOpen("libm.dylib"), State { next_error: Some(Error(OsError("dlopen(libm.dylibmassertion failed: `(left == right)`\n  left: ``,\n right: ``, 1): image not found", "dlopen"), State { next_error: None })) })', libcore/result.rs:945:5

os/unix/lib.rs implementation passes non-zero-terminated strings to dlopen/dlsym

E.g.:

let path_to_lib_str =
            path_to_lib
                .as_ref()
                .to_string_lossy();
        let path_to_lib_c_str = path_to_lib_str.as_ptr() as *const c_char;

here path_to_lib_c_str is not really a c_str, but a pointer to a regular Rust utf8 string slice. The issue can be reproduced with something like this:

let name = "mylib.so123";
LibUnsafe::new(&name[0..8]).unwrap();

where mylib.so is a valid shared lib that can be located by dlopen.

Update documentation with more specific information

The documentation could use some updating. Here is what I'm thinking:

  • Provide a small overview of LibArc and LibRc in the Choosing your guarantees section.
  • Provide more information about the methods on Data, Funcs, and Libs, especially information about unsafety and information about writing optimally performant code.
  • Describe the error types more clearly, especially SharedlibError. Include an example of error handling code.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.