diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 762c658ea6eb..4034d1ef8dd9 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2981,7 +2981,14 @@ pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta, llvm::LLVMAddGlobal(llmod, maptype.to_ref(), buf) } }; - lib::llvm::SetLinkage(map, lib::llvm::ExternalLinkage); + // On windows we'd like to export the toplevel cratemap + // such that we can find it from libstd. + if targ_cfg.os == session::OsWin32 && "toplevel" == mapname { + lib::llvm::SetLinkage(map, lib::llvm::DLLExportLinkage); + } else { + lib::llvm::SetLinkage(map, lib::llvm::ExternalLinkage); + } + return map; } @@ -3136,6 +3143,26 @@ pub fn trans_crate(sess: session::Session, decl_gc_metadata(ccx, llmod_id); fill_crate_map(ccx, ccx.crate_map); + + // NOTE win32: wart with exporting crate_map symbol + // We set the crate map (_rust_crate_map_toplevel) to use dll_export + // linkage but that ends up causing the linker to look for a + // __rust_crate_map_toplevel symbol (extra underscore) which it will + // subsequently fail to find. So to mitigate that we just introduce + // an alias from the symbol it expects to the one that actually exists. + if ccx.sess.targ_cfg.os == session::OsWin32 && + !*ccx.sess.building_library { + + let maptype = val_ty(ccx.crate_map).to_ref(); + + do "__rust_crate_map_toplevel".with_c_str |buf| { + unsafe { + llvm::LLVMAddAlias(ccx.llmod, maptype, + ccx.crate_map, buf); + } + } + } + glue::emit_tydescs(ccx); write_abi_version(ccx); if ccx.sess.opts.debuginfo { diff --git a/src/libstd/rt/crate_map.rs b/src/libstd/rt/crate_map.rs index e4c3763be96a..f73aa1fad67d 100644 --- a/src/libstd/rt/crate_map.rs +++ b/src/libstd/rt/crate_map.rs @@ -23,8 +23,8 @@ use container::MutableSet; #[link_args = "-undefined dynamic_lookup"] extern {} +#[cfg(not(stage0), not(windows))] extern { - #[cfg(not(stage0))] #[weak_linkage] #[link_name = "_rust_crate_map_toplevel"] static CRATE_MAP: CrateMap; @@ -48,11 +48,30 @@ struct CrateMap { children: [*CrateMap, ..1] } -#[cfg(not(stage0))] +#[cfg(not(stage0), not(windows))] pub fn get_crate_map() -> *CrateMap { &'static CRATE_MAP as *CrateMap } +#[cfg(not(stage0), windows)] +#[fixed_stack_segment] +#[inline(never)] +pub fn get_crate_map() -> *CrateMap { + use c_str::ToCStr; + use unstable::dynamic_lib::dl; + + let sym = unsafe { + let module = dl::open_internal(); + let sym = do "__rust_crate_map_toplevel".with_c_str |buf| { + dl::symbol(module, buf) + }; + dl::close(module); + sym + }; + + sym as *CrateMap +} + unsafe fn version(crate_map: *CrateMap) -> i32 { match (*crate_map).version { 1 => return 1, diff --git a/src/libstd/unstable/dynamic_lib.rs b/src/libstd/unstable/dynamic_lib.rs index 4c92d9c2e362..41ff79bc8845 100644 --- a/src/libstd/unstable/dynamic_lib.rs +++ b/src/libstd/unstable/dynamic_lib.rs @@ -138,7 +138,7 @@ mod test { #[cfg(target_os = "android")] #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] -mod dl { +pub mod dl { use c_str::ToCStr; use libc; use path; @@ -207,7 +207,7 @@ mod dl { } #[cfg(target_os = "win32")] -mod dl { +pub mod dl { use os; use libc; use path;