about summary refs log tree commit diff
path: root/src/libstd/rt
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd/rt')
-rw-r--r--src/libstd/rt/crate_map.rs51
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));
         }
     }
 }