@@ -1976,9 +1976,11 @@ fn add_linked_symbol_object(
19761976 cmd : & mut dyn Linker ,
19771977 sess : & Session ,
19781978 tmpdir : & Path ,
1979- symbols : & [ ( String , SymbolExportKind ) ] ,
1979+ crate_type : CrateType ,
1980+ linked_symbols : & [ ( String , SymbolExportKind ) ] ,
1981+ exported_symbols : & [ String ] ,
19801982) {
1981- if symbols . is_empty ( ) {
1983+ if linked_symbols . is_empty ( ) && exported_symbols . is_empty ( ) {
19821984 return ;
19831985 }
19841986
@@ -2015,7 +2017,7 @@ fn add_linked_symbol_object(
20152017 None
20162018 } ;
20172019
2018- for ( sym, kind) in symbols . iter ( ) {
2020+ for ( sym, kind) in linked_symbols . iter ( ) {
20192021 let symbol = file. add_symbol ( object:: write:: Symbol {
20202022 name : sym. clone ( ) . into ( ) ,
20212023 value : 0 ,
@@ -2073,6 +2075,38 @@ fn add_linked_symbol_object(
20732075 }
20742076 }
20752077
2078+ if sess. target . is_like_msvc {
2079+ // Symbol visibility takes care of this for executables typically
2080+ let should_filter_symbols = if crate_type == CrateType :: Executable {
2081+ sess. opts . unstable_opts . export_executable_symbols
2082+ } else {
2083+ true
2084+ } ;
2085+ if should_filter_symbols {
2086+ // Currently the compiler doesn't use `dllexport` (an LLVM attribute) to
2087+ // export symbols from a dynamic library. When building a dynamic library,
2088+ // however, we're going to want some symbols exported, so this adds a
2089+ // `.drectve` section which lists all the symbols using /EXPORT arguments.
2090+ //
2091+ // The linker will read these arguments from the `.drectve` section and
2092+ // export all the symbols from the dynamic library. Note that this is not
2093+ // as simple as just exporting all the symbols in the current crate (as
2094+ // specified by `codegen.reachable`) but rather we also need to possibly
2095+ // export the symbols of upstream crates. Upstream rlibs may be linked
2096+ // statically to this dynamic library, in which case they may continue to
2097+ // transitively be used and hence need their symbols exported.
2098+ let drectve = exported_symbols
2099+ . into_iter ( )
2100+ . map ( |sym| format ! ( " /EXPORT:\" {sym}\" " ) )
2101+ . collect :: < Vec < _ > > ( )
2102+ . join ( "" ) ;
2103+
2104+ let section =
2105+ file. add_section ( vec ! [ ] , b".drectve" . to_vec ( ) , object:: SectionKind :: Linker ) ;
2106+ file. append_section_data ( section, drectve. as_bytes ( ) , 1 ) ;
2107+ }
2108+ }
2109+
20762110 let path = tmpdir. join ( "symbols.o" ) ;
20772111 let result = std:: fs:: write ( & path, file. write ( ) . unwrap ( ) ) ;
20782112 if let Err ( error) = result {
@@ -2247,7 +2281,9 @@ fn linker_with_args(
22472281 cmd,
22482282 sess,
22492283 tmpdir,
2284+ crate_type,
22502285 & codegen_results. crate_info . linked_symbols [ & crate_type] ,
2286+ & codegen_results. crate_info . exported_symbols [ & crate_type] ,
22512287 ) ;
22522288
22532289 // Sanitizer libraries.
0 commit comments