@@ -1957,9 +1957,11 @@ fn add_linked_symbol_object(
19571957 cmd : & mut dyn Linker ,
19581958 sess : & Session ,
19591959 tmpdir : & Path ,
1960- symbols : & [ ( String , SymbolExportKind ) ] ,
1960+ crate_type : CrateType ,
1961+ linked_symbols : & [ ( String , SymbolExportKind ) ] ,
1962+ exported_symbols : & [ ( String , SymbolExportKind ) ] ,
19611963) {
1962- if symbols . is_empty ( ) {
1964+ if linked_symbols . is_empty ( ) && exported_symbols . is_empty ( ) {
19631965 return ;
19641966 }
19651967
@@ -1996,7 +1998,7 @@ fn add_linked_symbol_object(
19961998 None
19971999 } ;
19982000
1999- for ( sym, kind) in symbols . iter ( ) {
2001+ for ( sym, kind) in linked_symbols . iter ( ) {
20002002 let symbol = file. add_symbol ( object:: write:: Symbol {
20012003 name : sym. clone ( ) . into ( ) ,
20022004 value : 0 ,
@@ -2054,6 +2056,41 @@ fn add_linked_symbol_object(
20542056 }
20552057 }
20562058
2059+ if sess. target . is_like_msvc {
2060+ // Symbol visibility takes care of this for executables typically
2061+ let should_filter_symbols = if crate_type == CrateType :: Executable {
2062+ sess. opts . unstable_opts . export_executable_symbols
2063+ } else {
2064+ true
2065+ } ;
2066+ if should_filter_symbols {
2067+ // Currently the compiler doesn't use `dllexport` (an LLVM attribute) to
2068+ // export symbols from a dynamic library. When building a dynamic library,
2069+ // however, we're going to want some symbols exported, so this adds a
2070+ // `.drectve` section which lists all the symbols using /EXPORT arguments.
2071+ //
2072+ // The linker will read these arguments from the `.drectve` section and
2073+ // export all the symbols from the dynamic library. Note that this is not
2074+ // as simple as just exporting all the symbols in the current crate (as
2075+ // specified by `codegen.reachable`) but rather we also need to possibly
2076+ // export the symbols of upstream crates. Upstream rlibs may be linked
2077+ // statically to this dynamic library, in which case they may continue to
2078+ // transitively be used and hence need their symbols exported.
2079+ let drectve = exported_symbols
2080+ . into_iter ( )
2081+ . map ( |( sym, kind) | match kind {
2082+ SymbolExportKind :: Text | SymbolExportKind :: Tls => format ! ( " /EXPORT:\" {sym}\" " ) ,
2083+ SymbolExportKind :: Data => format ! ( " /EXPORT:\" {sym}\" ,DATA" ) ,
2084+ } )
2085+ . collect :: < Vec < _ > > ( )
2086+ . join ( "" ) ;
2087+
2088+ let section =
2089+ file. add_section ( vec ! [ ] , b".drectve" . to_vec ( ) , object:: SectionKind :: Linker ) ;
2090+ file. append_section_data ( section, drectve. as_bytes ( ) , 1 ) ;
2091+ }
2092+ }
2093+
20572094 let path = tmpdir. join ( "symbols.o" ) ;
20582095 let result = std:: fs:: write ( & path, file. write ( ) . unwrap ( ) ) ;
20592096 if let Err ( error) = result {
@@ -2228,7 +2265,9 @@ fn linker_with_args(
22282265 cmd,
22292266 sess,
22302267 tmpdir,
2268+ crate_type,
22312269 & codegen_results. crate_info . linked_symbols [ & crate_type] ,
2270+ & codegen_results. crate_info . exported_symbols [ & crate_type] ,
22322271 ) ;
22332272
22342273 // Sanitizer libraries.
0 commit comments