Skip to content

Commit 27ab9e5

Browse files
committed
staticlib symbol renaming: add -Zstaticlib-rename-internal-symbols
1 parent c7d4e98 commit 27ab9e5

21 files changed

Lines changed: 623 additions & 122 deletions

File tree

compiler/rustc_codegen_ssa/src/back/archive.rs

Lines changed: 305 additions & 95 deletions
Large diffs are not rendered by default.

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -525,15 +525,23 @@ fn link_staticlib(
525525
sess.dcx().emit_fatal(e);
526526
}
527527

528-
if sess.opts.unstable_opts.staticlib_hide_internal_symbols {
528+
if sess.opts.unstable_opts.staticlib_rename_internal_symbols {
529529
if !matches!(&*sess.target.archive_format, "gnu" | "bsd") {
530-
sess.dcx().emit_warn(errors::StaticlibHideInternalSymbolsUnsupported {
530+
sess.dcx().emit_warn(errors::StaticlibRenameInternalSymbolsUnsupported {
531531
archive_format: sess.target.archive_format.to_string(),
532532
});
533533
} else if let Some(symbols) = crate_info.exported_symbols.get(&CrateType::StaticLib) {
534534
use rustc_data_structures::fx::FxHashSet;
535535
let keep: FxHashSet<String> = symbols.iter().map(|(s, _)| s.clone()).collect();
536-
ab.set_keep_symbols(keep);
536+
// Generate a unique suffix from the crate name and a short hash
537+
// extracted from the metadata symbol (format: rust_metadata_{name}_{hash:08x}).
538+
let short_hash = crate_info
539+
.metadata_symbol
540+
.rsplit_once('_')
541+
.map(|(_, hash)| hash.to_string())
542+
.unwrap_or_else(|| format!("{:08x}", crate_info.local_crate_name.as_u32()));
543+
let suffix = format!("_rs{}", short_hash);
544+
ab.set_rename_symbols(keep, suffix);
537545
}
538546
}
539547

compiler/rustc_codegen_ssa/src/errors.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -677,9 +677,9 @@ pub(crate) struct BpfStaticlibNotSupported;
677677

678678
#[derive(Diagnostic)]
679679
#[diag(
680-
"-Zstaticlib-hide-internal-symbols only supports ELF archive formats (gnu/bsd), but the target uses `{$archive_format}`"
680+
"-Zstaticlib-rename-internal-symbols only supports ELF archive formats (gnu/bsd), but the target uses `{$archive_format}`"
681681
)]
682-
pub(crate) struct StaticlibHideInternalSymbolsUnsupported {
682+
pub(crate) struct StaticlibRenameInternalSymbolsUnsupported {
683683
pub archive_format: String,
684684
}
685685

compiler/rustc_interface/src/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -869,7 +869,7 @@ fn test_unstable_options_tracking_hash() {
869869
tracked!(split_lto_unit, Some(true));
870870
tracked!(src_hash_algorithm, Some(SourceFileHashAlgorithm::Sha1));
871871
tracked!(stack_protector, StackProtector::All);
872-
tracked!(staticlib_hide_internal_symbols, true);
872+
tracked!(staticlib_rename_internal_symbols, true);
873873
tracked!(teach, true);
874874
tracked!(thinlto, Some(true));
875875
tracked!(tiny_const_eval_limit, true);

compiler/rustc_session/src/config.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2474,10 +2474,11 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
24742474

24752475
let mut unstable_opts = UnstableOptions::build(early_dcx, matches, &mut collected_options);
24762476

2477-
if unstable_opts.staticlib_hide_internal_symbols && !crate_types.contains(&CrateType::StaticLib)
2477+
if unstable_opts.staticlib_rename_internal_symbols
2478+
&& !crate_types.contains(&CrateType::StaticLib)
24782479
{
24792480
early_dcx.early_fatal(
2480-
"-Zstaticlib-hide-internal-symbols can only be used with `--crate-type staticlib`",
2481+
"-Zstaticlib-rename-internal-symbols can only be used with `--crate-type staticlib`",
24812482
);
24822483
}
24832484

compiler/rustc_session/src/options.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2764,8 +2764,8 @@ written to standard error output)"),
27642764
"control stack smash protection strategy (`rustc --print stack-protector-strategies` for details)"),
27652765
staticlib_allow_rdylib_deps: bool = (false, parse_bool, [TRACKED],
27662766
"allow staticlibs to have rust dylib dependencies"),
2767-
staticlib_hide_internal_symbols: bool = (false, parse_bool, [TRACKED],
2768-
"hide Rust internal symbols when building staticlibs"),
2767+
staticlib_rename_internal_symbols: bool = (false, parse_bool, [TRACKED],
2768+
"rename Rust internal symbols when building staticlibs to avoid conflicts"),
27692769
staticlib_prefer_dynamic: bool = (false, parse_bool, [TRACKED],
27702770
"prefer dynamic linking to static linking for staticlibs (default: no)"),
27712771
strict_init_checks: bool = (false, parse_bool, [TRACKED],

src/doc/unstable-book/src/compiler-flags/staticlib-hide-internal-symbols.md

Lines changed: 0 additions & 10 deletions
This file was deleted.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# `staticlib-rename-internal-symbols`
2+
3+
When building a `staticlib`, this option renames all non-exported Rust-internal
4+
symbols by appending a `_rs{hash}` suffix and setting their ELF visibility to
5+
`STV_HIDDEN`. This prevents symbol collisions when multiple Rust static
6+
libraries are linked into the same final binary.
7+
8+
Only symbols explicitly exported via `#[no_mangle]` or `#[export_name]` are left
9+
unchanged. All other `GLOBAL`/`WEAK` symbols (including `pub(crate)` and `pub`
10+
items without `#[no_mangle]`) are renamed.
11+
12+
This option can only be used with `--crate-type staticlib`. Using it with
13+
other crate types will result in a compilation error.
14+
15+
Currently only ELF targets are supported (Linux, BSD, etc.). On non-ELF
16+
targets (macOS, Windows), a warning is emitted and the flag has no effect.

tests/run-make/staticlib-hide-internal-symbols/lib.rs renamed to tests/run-make/staticlib-rename-internal-symbols-visibility/lib.rs

File renamed without changes.

tests/run-make/staticlib-hide-internal-symbols/main.c renamed to tests/run-make/staticlib-rename-internal-symbols-visibility/main.c

File renamed without changes.

0 commit comments

Comments
 (0)