Skip to content

Need a way to load the _rust_crate_map_toplevel from a SO on Android #11731

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
larsbergstrom opened this issue Jan 22, 2014 · 6 comments
Closed
Labels
A-runtime Area: std's runtime and "pre-main" init for handling backtraces, unwinds, stack overflows

Comments

@larsbergstrom
Copy link
Contributor

For Servo on Android, Rust is unable to find the _rust_crate_map_toplevel because dlsym will not search all of the loaded modules in The Normal Way. This problem has caused us to currently change the implementation of get_crate_map as follows:

        let module = if cfg!(target_os = "android") {
            dl::open_external(&Path::new("/data/data/com.example.ServoAndroid/lib/libservo.so"))
        } else {
            dl::open_internal()
        };

It would be better if there was some way to provide the runtime with the name of the binary that contains the toplevel crate map.

CC: @aydinkim

@alexcrichton
Copy link
Member

Hm, this thread seems to indicate that this is "just how android is". As in, dlopen will not open dependent libraries, so you're forced to do the bottup-up dlopen calls yourself.

It appears that libreoffice has their own version of the function, lo_dlopen which does what I think it does on linux and co (reads the elf header and goes and dlopen's dependent libraries first).

http://motah.org.sa/dev/libreoffice.git/sal/android/lo-bootstrap.c
http://motah.org.sa/dev/libreoffice.git//android/Bootstrap/src/org/libreoffice/android/Bootstrap.java

Unsure if we'd want to bundle that inside of rust itself?

@larsbergstrom
Copy link
Contributor Author

The dlopen stuff has been fixed:

http://code.google.com/p/android/issues/detail?id=34416&can=1&q=dlopen&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars

The main problem for us (when using the windows path instead of the weak symbol path) is not that dlopen does not load dependencies, but that dlsym with RTLD_DEFAULT is not finding libservo.so and the _rust_crate_map_toplevel symbol.

@larsbergstrom
Copy link
Contributor Author

Could you possible expose a function that I could call from C to set the toplevel crate map? We're going to be looking to upgrade Rust soon, and without a way to help the Rust runtime find the crate map when loaded as a shared library, we will have to continue having a funky android-only patch that "knows" to look in the libservo.so crate for it, ala:
https://gist.github.com/larsbergstrom/9101334

(ignore all the debugging output :-))

@alexcrichton
Copy link
Member

Hm, I believe we could, I would imagine something along the lines of:

static mut MANUAL_CRATE_MAP: *CrateMap = 0 as *CrateMap;

#[no_mangle]
pub extern fn rust_set_crate_map(map: *CrateMap) {
    unsafe { MANUAL_CRATE_MAP = map; }
}

And then all functions using the crate map would check if MANUAL_CRATE_MAP were not null before looking for the dynamically linked or weak linked one. It seems bad that we would have to do this, but I'm not sure of a better situation for android.

Basically, yes, it could be possible.

@alexcrichton
Copy link
Member

@larsbergstrom, would something like that work for servo?

@larsbergstrom
Copy link
Contributor Author

Yes, definitely!

If it's easier, we can alternatively provide the module name to look in for the symbol (though I guess that only works on dlsym-using platforms.

Thanks!

alexcrichton added a commit to alexcrichton/rust that referenced this issue Feb 25, 2014
Apparently weak linkage and dlopen aren't quite working out for applications
like servo on android. There appears to be a bug or two in how android loads
dynamic libraries and for some reason libservo.so isn't being found.

As a temporary solution, add an extern "C" function to libstd which can be
called if you have a handle to the crate map manually. When crawling the crate
map, we then check this manual symbol before falling back to the old solutions.

cc rust-lang#11731
bors added a commit that referenced this issue Feb 25, 2014
Apparently weak linkage and dlopen aren't quite working out for applications
like servo on android. There appears to be a bug or two in how android loads
dynamic libraries and for some reason libservo.so isn't being found.

As a temporary solution, add an extern "C" function to libstd which can be
called if you have a handle to the crate map manually. When crawling the crate
map, we then check this manual symbol before falling back to the old solutions.

cc #11731
larsbergstrom pushed a commit to larsbergstrom/rust that referenced this issue Apr 1, 2014
Apparently weak linkage and dlopen aren't quite working out for applications
like servo on android. There appears to be a bug or two in how android loads
dynamic libraries and for some reason libservo.so isn't being found.

As a temporary solution, add an extern "C" function to libstd which can be
called if you have a handle to the crate map manually. When crawling the crate
map, we then check this manual symbol before falling back to the old solutions.

cc rust-lang#11731
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-runtime Area: std's runtime and "pre-main" init for handling backtraces, unwinds, stack overflows
Projects
None yet
Development

No branches or pull requests

2 participants