diff options
Diffstat (limited to 'src/libstd/rt')
| -rw-r--r-- | src/libstd/rt/crate_map.rs | 51 |
1 files changed, 43 insertions, 8 deletions
diff --git a/src/libstd/rt/crate_map.rs b/src/libstd/rt/crate_map.rs index 847375121c8..409b77d1a3f 100644 --- a/src/libstd/rt/crate_map.rs +++ b/src/libstd/rt/crate_map.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use cast; use cmp::TotalOrd; use container::MutableSet; use iter::Iterator; @@ -35,6 +36,34 @@ pub struct CrateMap<'a> { event_loop_factory: Option<fn() -> ~EventLoop>, } +// When working on android, apparently weak symbols don't work so well for +// finding the crate map, and neither does dlopen + dlsym. This is mainly a +// problem when integrating a shared library with an existing application. +// Standalone binaries do not appear to have this problem. The reasons are a +// little mysterious, and more information can be found in #11731. +// +// For now we provide a way to tell libstd about the crate map manually that's +// checked before the normal weak symbol/dlopen paths. In theory this is useful +// on other platforms where our dlopen/weak linkage strategy mysteriously fails +// but the crate map can be specified manually. +static mut MANUALLY_PROVIDED_CRATE_MAP: *CrateMap<'static> = + 0 as *CrateMap<'static>; +#[no_mangle] +#[cfg(not(test))] +pub extern fn rust_set_crate_map(map: *CrateMap<'static>) { + unsafe { MANUALLY_PROVIDED_CRATE_MAP = map; } +} + +fn manual_crate_map() -> Option<&'static CrateMap<'static>> { + unsafe { + if MANUALLY_PROVIDED_CRATE_MAP.is_null() { + None + } else { + Some(cast::transmute(MANUALLY_PROVIDED_CRATE_MAP)) + } + } +} + #[cfg(not(windows))] pub fn get_crate_map() -> Option<&'static CrateMap<'static>> { extern { @@ -42,20 +71,26 @@ pub fn get_crate_map() -> Option<&'static CrateMap<'static>> { static CRATE_MAP: CrateMap<'static>; } - let ptr: (*CrateMap) = &'static CRATE_MAP; - if ptr.is_null() { - return None; - } else { - return Some(&'static CRATE_MAP); - } + manual_crate_map().or_else(|| { + let ptr: (*CrateMap) = &'static CRATE_MAP; + if ptr.is_null() { + None + } else { + Some(&'static CRATE_MAP) + } + }) } #[cfg(windows)] pub fn get_crate_map() -> Option<&'static CrateMap<'static>> { - use cast::transmute; use c_str::ToCStr; use unstable::dynamic_lib::dl; + match manual_crate_map() { + Some(cm) => return Some(cm), + None => {} + } + let sym = unsafe { let module = dl::open_internal(); let rust_crate_map_toplevel = if cfg!(target_arch = "x86") { @@ -74,7 +109,7 @@ pub fn get_crate_map() -> Option<&'static CrateMap<'static>> { return None; } else { unsafe { - return Some(transmute(sym)); + return Some(cast::transmute(sym)); } } } |
