Code Monkey home page Code Monkey logo

rust-dlopen's People

Contributors

afinch7 avatar jackcmay avatar karrq avatar kzys avatar m-ou-se avatar szymonwieloch avatar zicklag 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  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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

rust-dlopen's Issues

Loading with RTLD_GLOBAL

I would like to load a library with RTLD_GLOBAL as I want to use the symbols for a subsequent library load. Can you add this option?

Add badges to cargo

Providing badges in cargo should improve outlook of the library and increase trust tothe library by users.

Get base address directly from Library

I'm using the raw API, and would like to get the DLL base address.

It's currently possible to use AddressInfoObtainer to get the base address, but that requires the user to supply an arbitrary symbol name to look up. It would be very convenient for my application if this wasn't necessary, and I could get it directly from the Library without needing a symbol name.

shouldn't raw::Library::open be unsafe?

I think open should probably be marked unsafe, because it could call a unsafe function, although not directly.

For example, below code demonstrates a constructor function is called on library load (no unsafe code needed):

cargo new dlopen-test
cd dlopen-test/

cat > hello.c << EOF
#include <stdio.h>

void __attribute__ ((constructor)) hello(void)
{
        printf("hello from C\n");
}
EOF

gcc -Wall -shared -fPIC -o hello.so hello.c
cat > src/main.rs << EOF
extern crate dlopen;
use dlopen::raw::Library;

fn main() {
    let lib = Library::open("./hello.so").unwrap();
}
EOF

cargo add dlopen
cargo run

# some cargo outputs, ends with this print from C code
hello from C

Safety against obtaining function pointers to functions removed by dlclose?

A dastardly user could:

  • Write a function that returns a function pointer to itself
  • Put that function inside a shared library
  • dlopen the library
  • Call the function
  • Store the returned fn
  • Call dlclose on the library
  • Try to call the fn. Boom?

Does the crate have anything to prevent this? I see the Symbol types that are trying to ensure you only call a function if it's still loaded as long as you are going through them, but it seems like it's possible for users to circumvent by having functions that return function pointers, but I'm still new to Rust and I haven't actually tried coding this up so I could be wrong.

Test open_play_close_raw fails on macOS High Sierra (10.13.6)

RUST_BACKTRACE=1 cargo test fails on my laptop:

     Running target/debug/deps/raw-5bfffb8910e2b187

running 1 test
test open_play_close_raw ... FAILED

failures:

---- open_play_close_raw stdout ----
Library path: /Users/maoe/src/github.com/szymonwieloch/rust-dlopen/target/debug/deps/libexample.dylib.dSYM
thread 'open_play_close_raw' panicked at 'Could not open library: OpeningLibraryError(Custom { kind: Other, error: StringError("dlopen(/Users/maoe/src/github.com/szymonwieloch/rust-dlopen/target/debug/deps/libexample.dylib.dSYM, 5): no suitable image found.  Did find:\n\t/Users/maoe/src/github.com/szymonwieloch/rust-dlopen/target/debug/deps/libexample.dylib.dSYM: not a file\n\t/Users/maoe/src/github.com/szymonwieloch/rust-dlopen/target/debug/deps/libexample.dylib.dSYM: not a file\n\t/Users/maoe/src/github.com/szymonwieloch/rust-dlopen/target/debug/deps/libexample.dylib.dSYM: not a file\n\t/Users/maoe/src/github.com/szymonwieloch/rust-dlopen/target/debug/deps/libexample.dylib.dSYM: not a file") })', libcore/result.rs:945:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
             at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1: std::sys_common::backtrace::print
             at libstd/sys_common/backtrace.rs:71
             at libstd/sys_common/backtrace.rs:59
   2: std::panicking::default_hook::{{closure}}
             at libstd/panicking.rs:211
   3: std::panicking::default_hook
             at libstd/panicking.rs:221
   4: <std::panicking::begin_panic::PanicPayload<A> as core::panic::BoxMeUp>::get
             at libstd/panicking.rs:511
   5: std::panicking::continue_panic_fmt
             at libstd/panicking.rs:426
   6: std::panicking::try::do_call
             at libstd/panicking.rs:337
   7: <T as core::any::Any>::get_type_id
             at libcore/panicking.rs:92
   8: core::result::unwrap_failed
             at /private/tmp/rust-20180803-66047-v6t750/rustc-1.28.0-src/src/libcore/macros.rs:26
   9: <core::result::Result<T, E>>::expect
             at /private/tmp/rust-20180803-66047-v6t750/rustc-1.28.0-src/src/libcore/result.rs:809
  10: raw::open_play_close_raw
             at tests/raw.rs:16
  11: raw::__test::TESTS::{{closure}}
             at tests/raw.rs:14
  12: core::ops::function::FnOnce::call_once
             at /private/tmp/rust-20180803-66047-v6t750/rustc-1.28.0-src/src/libcore/ops/function.rs:223
  13: <F as alloc::boxed::FnBox<A>>::call_box
             at libtest/lib.rs:1451
             at /private/tmp/rust-20180803-66047-v6t750/rustc-1.28.0-src/src/libcore/ops/function.rs:223
             at /private/tmp/rust-20180803-66047-v6t750/rustc-1.28.0-src/src/liballoc/boxed.rs:640
  14: panic_unwind::dwarf::eh::read_encoded_pointer
             at libpanic_unwind/lib.rs:105


failures:
    open_play_close_raw

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out

error: test failed, to rerun pass '--test raw'

As the error message says libexample.dylib.dSYM is indeed not a file. It's a bundle which contains a shared lib.

% tree target/debug/deps/libexample.dylib.dSYM/                                                                  
target/debug/deps/libexample.dylib.dSYM/
└── Contents
    ├── Info.plist
    └── Resources
        └── DWARF
            └── libexample.dylib

3 directories, 2 files
% file target/debug/deps/libexample.dylib.dSYM/Contents/Resources/DWARF/libexample.dylib
target/debug/deps/libexample.dylib.dSYM/Contents/Resources/DWARF/libexample.dylib: Mach-O 64-bit dSYM companion file x86_64

I'm testing this with the current master with rustc 1.28.0.

Library:: open error - code 126

Trying to open a DLL by full path wrapped in OsStr on windows 10. But error code 126 / The specified module could not be found, raised.

When passing path directly to open function, it works!?

Tks

Public fields for derive(WrapperApi)

Why doesn't the macro allow the fields to be public? Or is there a way I don't know of?

I'm a noob at this stuff, so I don't know if there is a reason or if it just was never implemented. It's super frustrating that this is the only thing holding me back on my project..

Is `rust-dlopen` maintained?

This library looks promising for my needs, but looks like not much has happened for a while?
What is the plan with this library, is it going to be maintained?

`dlerror` *is* thread-safe on some platforms

I can see in the source code that there's a global lock for dlerror, since this crate assumes that it's not thread-safe. However, the manuals for Linux and macOS do indicate that their implementation is thread-safe:

Perhaps that lock could only be used on platforms other than these (or any more that might come up).

Also, the table about libloading not being thread-safe is slightly wrong, AFAIK (https://docs.rs/dlopen/0.1.8/dlopen/#compare-with-other-libraries). Internally, libloading uses SetThreadErrorMode (maybe it didn't in the past), which means that it's thread safe on Windows. The issue it has is that on FreeBSD, for example, dlerror isn't thread-safe.

Increase verbosity of SymbolGettingError

I am using the library to verify that a dynamic linked library exports a specific set of symbols.

Currently, the library returns an error in cases of missing symbols that do not list the specific symbol missing:

SymbolGettingError(Os { code: 127, kind: Other, message: "The specified procedure could not be found." })

For troubleshooting bigger libraries it would be very useful if the missing symbol would be included in the message, like:

SymbolGettingError(Os { code: 127, kind: Other, message: "The specified procedure "foo" could not be found." })

Re-Export the derive macro from the dlopen crate

Currently, to use dlopen, the user needs 2 dependencies, one for the derive macro and one for the library itself

dlopen = "0.1"
dlopen_derive = "0.1"

as well as this extra dependency, crates also need to #[macro_use] the derive crate in order to use the macro

#[macro_use]
extern crate dlopen_derive;

This could be remedied by putting the above statement in the dlopen crate itself, much like how serde re-exports the Serialize and Deserialize dervive macros (https://github.com/serde-rs/serde/blob/master/serde/src/lib.rs#L278-L289). So the user would only need to use the trait and it would also import the macro under the same name.

It might also be possible to do this in the wrapper module rather than the crate root so that the user importing the trait use dlopen::wrapper::WrapperApi they would also import the derive macro of that name.

Usage in no-std environment?

This is reported when turning on the #![no-std].

  dlopen-test on  main [?] via 🦀 v1.60.0-nightly ✗✗✗ RUSTFLAGS="-Z macro-backtrace" cargo build --release
error[E0433]: failed to resolve: could not find `std` in the list of imported crates
  --> src/main.rs:24:10
   |
24 | #[derive(WrapperApi)]
   |          ^^^^^^^^^^
   |          |
   |          could not find `std` in the list of imported crates
   |          in this derive macro expansion
   |
  ::: /home/animesh/.cargo/registry/src/github.com-1ecc6299db9ec823/dlopen_derive-0.1.4/src/lib.rs:23:1
   |
23 | pub fn wrapper_api(input: TokenStream) -> TokenStream {
   | ----------------------------------------------------- in this expansion of `#[derive(WrapperApi)]`

Create one best safe API.

Refactor wrapper API and and Symbor API to provide one consistent API with additional thread safety

#[derive(WrapperApi)] fails if `use std::io::Result;`

This fails to compile for me:

#[macro_use]                                                                                         
extern crate dlopen_derive;                                                                          
extern crate dlopen;                                                                                 
use dlopen::wrapper::WrapperApi;                                                                     
                                                                                                     
use std::io::Result;                                                                                 
                                                                                                     
#[derive(WrapperApi)]                                                                                
struct Example {                                                                                     
    do_something: extern "C" fn(),                                                                   
}                                                                                                    
                                                                                                     
fn main () {                                                                                         
}

The error is:

error[E0244]: wrong number of type arguments: expected 1, found 2
 --> src/main.rs:8:10
  |
8 | #[derive(WrapperApi)]
  |          ^^^^^^^^^^ expected 1 type argument

error: aborting due to previous error

(if I take out the use std::io::Result; line, it compiles)

Typo in error message

I got this today. I think it is missing an -> and is desired here.

   |
74 | #[derive(WrapperApi)]
   |          ^^^^^^^^^^
   |
   = help: message: Only bare functions, references an pointers are allowed in structures implementing WrapperApi trait

dlopen 0.1.8
dlopen_derive 0.1.4

Panic due to double SymInitializeW

Rust on Windows has to call SymInitializeW before generating a backtrace, and it doesn't call SymCleanup afterward. If AddressInfoObtainer is then used, it calls SymInitializeW again, which fails because it has already been called.

Example code (set RUSTBACKTRACE=1):

use std::panic::catch_unwind;
use dlopen::raw::{AddressInfoObtainer, Library};

fn main() {
    let library = Library::open("example.dll").unwrap();
    let pointer: *const () = unsafe { library.symbol("foo") }.unwrap();

    catch_unwind(|| panic!()); // this generates a backtrace. Backtrace::capture() probably works too

    // Panics because SymInitializeW returns an error
    AddressInfoObtainer::new().obtain(pointer).unwrap();
}

There is some background on how the backtrace crate handled a similar conflict here (also explains why Rust doesn't call SymCleanup).

I think dlopen should:

  • Call SymInitializeW but ignore its return value
  • Never call SymCleanup

This behavior is awkward, but I think it's the only way to be compatible with how Rust uses SymInitializeW.

I can submit a PR for this if it's welcome.

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.