Skip to content

Commit fbb1950

Browse files
committed
Auto merge of #158294 - AsakuraMizu:windows-drectve-export, r=<try>
Use .drectve for MSVC DLL exports try-job: x86_64-msvc-1
2 parents 63f05e3 + c84bcbe commit fbb1950

6 files changed

Lines changed: 184 additions & 138 deletions

File tree

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@ use super::rmeta_link::RmetaLinkCache;
6363
use super::rpath::{self, RPathConfig};
6464
use super::{apple, rmeta_link, versioned_llvm_target};
6565
use crate::base::needs_allocator_shim_for_linking;
66-
use crate::{CodegenLintLevelSpecs, CompiledModule, CompiledModules, CrateInfo, NativeLib, errors};
66+
use crate::{
67+
CodegenLintLevelSpecs, CompiledModule, CompiledModules, CrateInfo, NativeLib, SymbolExport,
68+
errors,
69+
};
6770

6871
pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) {
6972
if let Err(e) = fs::remove_file(path) {
@@ -593,7 +596,7 @@ fn link_staticlib(
593596
crate_info
594597
.exported_symbols
595598
.get(&CrateType::StaticLib)
596-
.map(|symbols| symbols.iter().map(|(s, _)| s.clone()).collect())
599+
.map(|symbols| symbols.iter().map(|symbol| symbol.name.clone()).collect())
597600
}
598601
} else {
599602
None
@@ -2196,9 +2199,15 @@ fn add_linked_symbol_object(
21962199
cmd: &mut dyn Linker,
21972200
sess: &Session,
21982201
tmpdir: &Path,
2199-
symbols: &[(String, SymbolExportKind)],
2202+
crate_type: CrateType,
2203+
linked_symbols: &[(String, SymbolExportKind)],
2204+
exported_symbols: &[SymbolExport],
22002205
) {
2201-
if symbols.is_empty() {
2206+
let should_export_symbols = sess.target.is_like_msvc
2207+
&& !exported_symbols.is_empty()
2208+
&& (crate_type != CrateType::Executable
2209+
|| sess.opts.unstable_opts.export_executable_symbols);
2210+
if linked_symbols.is_empty() && !should_export_symbols {
22022211
return;
22032212
}
22042213

@@ -2235,7 +2244,7 @@ fn add_linked_symbol_object(
22352244
None
22362245
};
22372246

2238-
for (sym, kind) in symbols.iter() {
2247+
for (sym, kind) in linked_symbols.iter() {
22392248
let symbol = file.add_symbol(object::write::Symbol {
22402249
name: sym.clone().into(),
22412250
value: 0,
@@ -2293,6 +2302,37 @@ fn add_linked_symbol_object(
22932302
}
22942303
}
22952304

2305+
if should_export_symbols {
2306+
// Currently the compiler doesn't use `dllexport` (an LLVM attribute) to
2307+
// export symbols from a dynamic library. When building a dynamic library,
2308+
// however, we're going to want some symbols exported, so this adds a
2309+
// `.drectve` section which lists all the symbols using /EXPORT arguments.
2310+
//
2311+
// The linker will read these arguments from the `.drectve` section and
2312+
// export all the symbols from the dynamic library. Note that this is not
2313+
// as simple as just exporting all the symbols in the current crate (as
2314+
// specified by `codegen.reachable`) but rather we also need to possibly
2315+
// export the symbols of upstream crates. Upstream rlibs may be linked
2316+
// statically to this dynamic library, in which case they may continue to
2317+
// transitively be used and hence need their symbols exported.
2318+
fn msvc_drectve_export(symbol: &SymbolExport) -> String {
2319+
let data = if symbol.kind == SymbolExportKind::Data { ",DATA" } else { "" };
2320+
2321+
if let Some(link_name) = symbol.link_name.as_deref() {
2322+
// The first name is the decorated symbol used by the import library, while
2323+
// EXPORTAS gives the public name written to the DLL export table.
2324+
format!(" /EXPORT:\"{link_name}\"{data},EXPORTAS,\"{}\"", symbol.name)
2325+
} else {
2326+
format!(" /EXPORT:\"{}\"{data}", symbol.name)
2327+
}
2328+
}
2329+
2330+
let drectve = exported_symbols.iter().map(msvc_drectve_export).collect::<String>();
2331+
2332+
let section = file.add_section(vec![], b".drectve".to_vec(), object::SectionKind::Linker);
2333+
file.append_section_data(section, drectve.as_bytes(), 1);
2334+
}
2335+
22962336
let path = tmpdir.join("symbols.o");
22972337
let result = std::fs::write(&path, file.write().unwrap());
22982338
if let Err(error) = result {
@@ -2486,7 +2526,7 @@ fn undecorate_c_symbol<'a>(
24862526
fn add_c_staticlib_symbols(
24872527
sess: &Session,
24882528
lib: &NativeLib,
2489-
out: &mut Vec<(String, SymbolExportKind)>,
2529+
out: &mut Vec<SymbolExport>,
24902530
) -> io::Result<()> {
24912531
let file_path = find_native_static_library(lib.name.as_str(), lib.verbatim, sess);
24922532

@@ -2549,7 +2589,11 @@ fn add_c_staticlib_symbols(
25492589
let Some(undecorated) = undecorate_c_symbol(name, sess, export_kind) else {
25502590
continue;
25512591
};
2552-
out.push((undecorated.to_string(), export_kind));
2592+
out.push(SymbolExport::with_link_name(
2593+
undecorated.to_string(),
2594+
export_kind,
2595+
name.to_string(),
2596+
));
25532597
}
25542598
}
25552599

@@ -2629,7 +2673,14 @@ fn linker_with_args(
26292673
// Pre-link CRT objects.
26302674
add_pre_link_objects(cmd, sess, flavor, link_output_kind, self_contained_crt_objects);
26312675

2632-
add_linked_symbol_object(cmd, sess, tmpdir, &crate_info.linked_symbols[&crate_type]);
2676+
add_linked_symbol_object(
2677+
cmd,
2678+
sess,
2679+
tmpdir,
2680+
crate_type,
2681+
&crate_info.linked_symbols[&crate_type],
2682+
&export_symbols,
2683+
);
26332684

26342685
// Sanitizer libraries.
26352686
add_sanitizer_libraries(sess, flavor, crate_type, cmd);

0 commit comments

Comments
 (0)