@@ -1957,9 +1957,11 @@ fn add_linked_symbol_object(
1957
1957
cmd : & mut dyn Linker ,
1958
1958
sess : & Session ,
1959
1959
tmpdir : & Path ,
1960
- symbols : & [ ( String , SymbolExportKind ) ] ,
1960
+ crate_type : CrateType ,
1961
+ linked_symbols : & [ ( String , SymbolExportKind ) ] ,
1962
+ exported_symbols : & [ ( String , SymbolExportKind ) ] ,
1961
1963
) {
1962
- if symbols . is_empty ( ) {
1964
+ if linked_symbols . is_empty ( ) && exported_symbols . is_empty ( ) {
1963
1965
return ;
1964
1966
}
1965
1967
@@ -1996,7 +1998,7 @@ fn add_linked_symbol_object(
1996
1998
None
1997
1999
} ;
1998
2000
1999
- for ( sym, kind) in symbols . iter ( ) {
2001
+ for ( sym, kind) in linked_symbols . iter ( ) {
2000
2002
let symbol = file. add_symbol ( object:: write:: Symbol {
2001
2003
name : sym. clone ( ) . into ( ) ,
2002
2004
value : 0 ,
@@ -2054,6 +2056,41 @@ fn add_linked_symbol_object(
2054
2056
}
2055
2057
}
2056
2058
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
+
2057
2094
let path = tmpdir. join ( "symbols.o" ) ;
2058
2095
let result = std:: fs:: write ( & path, file. write ( ) . unwrap ( ) ) ;
2059
2096
if let Err ( error) = result {
@@ -2228,7 +2265,9 @@ fn linker_with_args(
2228
2265
cmd,
2229
2266
sess,
2230
2267
tmpdir,
2268
+ crate_type,
2231
2269
& codegen_results. crate_info . linked_symbols [ & crate_type] ,
2270
+ & codegen_results. crate_info . exported_symbols [ & crate_type] ,
2232
2271
) ;
2233
2272
2234
2273
// Sanitizer libraries.
0 commit comments