about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libstd/rt/crate_map.rs51
-rw-r--r--src/test/run-make/c-set-crate-map-manually/Makefile7
-rw-r--r--src/test/run-make/c-set-crate-map-manually/lib.rs30
-rw-r--r--src/test/run-make/c-set-crate-map-manually/main.c20
4 files changed, 100 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));
         }
     }
 }
diff --git a/src/test/run-make/c-set-crate-map-manually/Makefile b/src/test/run-make/c-set-crate-map-manually/Makefile
new file mode 100644
index 00000000000..954f10d3edd
--- /dev/null
+++ b/src/test/run-make/c-set-crate-map-manually/Makefile
@@ -0,0 +1,7 @@
+-include ../tools.mk
+
+all:
+	$(RUSTC) lib.rs -C gen-crate-map
+	ln -nsf $(call DYLIB,boot-*) $(call DYLIB,boot)
+	$(CC) main.c -o $(call RUN,main) -lboot -Wl,-rpath,$(TMPDIR)
+	RUST_LOG=boot $(call RUN,main)
diff --git a/src/test/run-make/c-set-crate-map-manually/lib.rs b/src/test/run-make/c-set-crate-map-manually/lib.rs
new file mode 100644
index 00000000000..15b0a9140cf
--- /dev/null
+++ b/src/test/run-make/c-set-crate-map-manually/lib.rs
@@ -0,0 +1,30 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[crate_id="boot#0.1"];
+#[crate_type="dylib"];
+#[no_uv];
+
+extern crate rustuv;
+extern crate green;
+
+use std::rt::crate_map::{CrateMap, rust_set_crate_map};
+
+// pull in this symbol from libstd into this crate (for convenience)
+#[no_mangle]
+pub static set_crate_map: extern "C" fn(*CrateMap<'static>) = rust_set_crate_map;
+
+#[no_mangle] // this needs to get called from C
+pub extern "C" fn foo(argc: int, argv: **u8) -> int {
+    green::start(argc, argv, proc() {
+        if log_enabled!(std::logging::DEBUG) { return }
+        fail!()
+    })
+}
diff --git a/src/test/run-make/c-set-crate-map-manually/main.c b/src/test/run-make/c-set-crate-map-manually/main.c
new file mode 100644
index 00000000000..a69ec7d0c86
--- /dev/null
+++ b/src/test/run-make/c-set-crate-map-manually/main.c
@@ -0,0 +1,20 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// this is the rust entry point that we're going to call.
+int foo(int argc, char *argv[]);
+
+extern void (*set_crate_map)(void *map);
+extern int _rust_crate_map_toplevel;
+
+int main(int argc, char *argv[]) {
+  set_crate_map(&_rust_crate_map_toplevel);
+  return foo(argc, argv);
+}