@@ -62,7 +62,10 @@ use super::metadata::{MetadataPosition, create_wrapper_file};
6262use super :: rpath:: { self , RPathConfig } ;
6363use super :: { apple, rmeta_link, versioned_llvm_target} ;
6464use crate :: base:: needs_allocator_shim_for_linking;
65- use crate :: { CodegenLintLevelSpecs , CompiledModule , CompiledModules , CrateInfo , NativeLib , errors} ;
65+ use crate :: {
66+ CodegenLintLevelSpecs , CompiledModule , CompiledModules , CrateInfo , NativeLib , SymbolExport ,
67+ errors,
68+ } ;
6669
6770pub fn ensure_removed ( dcx : DiagCtxtHandle < ' _ > , path : & Path ) {
6871 if let Err ( e) = fs:: remove_file ( path) {
@@ -588,7 +591,7 @@ fn link_staticlib(
588591 crate_info
589592 . exported_symbols
590593 . get ( & CrateType :: StaticLib )
591- . map ( |symbols| symbols. iter ( ) . map ( |( s , _ ) | s . clone ( ) ) . collect ( ) )
594+ . map ( |symbols| symbols. iter ( ) . map ( |symbol| symbol . name . clone ( ) ) . collect ( ) )
592595 }
593596 } else {
594597 None
@@ -2189,9 +2192,15 @@ fn add_linked_symbol_object(
21892192 cmd : & mut dyn Linker ,
21902193 sess : & Session ,
21912194 tmpdir : & Path ,
2192- symbols : & [ ( String , SymbolExportKind ) ] ,
2195+ crate_type : CrateType ,
2196+ linked_symbols : & [ ( String , SymbolExportKind ) ] ,
2197+ exported_symbols : & [ SymbolExport ] ,
21932198) {
2194- if symbols. is_empty ( ) {
2199+ let should_export_symbols = sess. target . is_like_msvc
2200+ && !exported_symbols. is_empty ( )
2201+ && ( crate_type != CrateType :: Executable
2202+ || sess. opts . unstable_opts . export_executable_symbols ) ;
2203+ if linked_symbols. is_empty ( ) && !should_export_symbols {
21952204 return ;
21962205 }
21972206
@@ -2228,7 +2237,7 @@ fn add_linked_symbol_object(
22282237 None
22292238 } ;
22302239
2231- for ( sym, kind) in symbols . iter ( ) {
2240+ for ( sym, kind) in linked_symbols . iter ( ) {
22322241 let symbol = file. add_symbol ( object:: write:: Symbol {
22332242 name : sym. clone ( ) . into ( ) ,
22342243 value : 0 ,
@@ -2286,6 +2295,37 @@ fn add_linked_symbol_object(
22862295 }
22872296 }
22882297
2298+ if should_export_symbols {
2299+ // Currently the compiler doesn't use `dllexport` (an LLVM attribute) to
2300+ // export symbols from a dynamic library. When building a dynamic library,
2301+ // however, we're going to want some symbols exported, so this adds a
2302+ // `.drectve` section which lists all the symbols using /EXPORT arguments.
2303+ //
2304+ // The linker will read these arguments from the `.drectve` section and
2305+ // export all the symbols from the dynamic library. Note that this is not
2306+ // as simple as just exporting all the symbols in the current crate (as
2307+ // specified by `codegen.reachable`) but rather we also need to possibly
2308+ // export the symbols of upstream crates. Upstream rlibs may be linked
2309+ // statically to this dynamic library, in which case they may continue to
2310+ // transitively be used and hence need their symbols exported.
2311+ fn msvc_drectve_export ( symbol : & SymbolExport ) -> String {
2312+ let data = if symbol. kind == SymbolExportKind :: Data { ",DATA" } else { "" } ;
2313+
2314+ if let Some ( link_name) = symbol. link_name . as_deref ( ) {
2315+ // The first name is the decorated symbol used by the import library, while
2316+ // EXPORTAS gives the public name written to the DLL export table.
2317+ format ! ( " /EXPORT:\" {link_name}\" {data},EXPORTAS,\" {}\" " , symbol. name)
2318+ } else {
2319+ format ! ( " /EXPORT:\" {}\" {data}" , symbol. name)
2320+ }
2321+ }
2322+
2323+ let drectve = exported_symbols. iter ( ) . map ( msvc_drectve_export) . collect :: < String > ( ) ;
2324+
2325+ let section = file. add_section ( vec ! [ ] , b".drectve" . to_vec ( ) , object:: SectionKind :: Linker ) ;
2326+ file. append_section_data ( section, drectve. as_bytes ( ) , 1 ) ;
2327+ }
2328+
22892329 let path = tmpdir. join ( "symbols.o" ) ;
22902330 let result = std:: fs:: write ( & path, file. write ( ) . unwrap ( ) ) ;
22912331 if let Err ( error) = result {
@@ -2416,7 +2456,7 @@ fn add_rpath_args(
24162456fn add_c_staticlib_symbols (
24172457 sess : & Session ,
24182458 lib : & NativeLib ,
2419- out : & mut Vec < ( String , SymbolExportKind ) > ,
2459+ out : & mut Vec < SymbolExport > ,
24202460) -> io:: Result < ( ) > {
24212461 let file_path = find_native_static_library ( lib. name . as_str ( ) , lib. verbatim , sess) ;
24222462
@@ -2469,9 +2509,9 @@ fn add_c_staticlib_symbols(
24692509 _ => continue ,
24702510 } ;
24712511
2472- // FIXME:The symbol mangle rules are slightly different in Windows(32-bit) and Apple .
2473- // Need to be resolved .
2474- out. push ( ( name. to_string ( ) , export_kind) ) ;
2512+ // Names read from the object file are already linker-visible .
2513+ // Do not apply symbol decoration again here .
2514+ out. push ( SymbolExport :: new ( name. to_string ( ) , export_kind) ) ;
24752515 }
24762516 }
24772517
@@ -2550,7 +2590,14 @@ fn linker_with_args(
25502590 // Pre-link CRT objects.
25512591 add_pre_link_objects ( cmd, sess, flavor, link_output_kind, self_contained_crt_objects) ;
25522592
2553- add_linked_symbol_object ( cmd, sess, tmpdir, & crate_info. linked_symbols [ & crate_type] ) ;
2593+ add_linked_symbol_object (
2594+ cmd,
2595+ sess,
2596+ tmpdir,
2597+ crate_type,
2598+ & crate_info. linked_symbols [ & crate_type] ,
2599+ & export_symbols,
2600+ ) ;
25542601
25552602 // Sanitizer libraries.
25562603 add_sanitizer_libraries ( sess, flavor, crate_type, cmd) ;
0 commit comments