Skip to content

Commit 0633073

Browse files
committed
MCP rust-lang#705: Provide the option -Zsymbol-mangling-version=hashed to shorten symbol names by replacing them with a digest.
Enrich test cases
1 parent 714b29a commit 0633073

File tree

14 files changed

+153
-11
lines changed

14 files changed

+153
-11
lines changed

compiler/rustc_session/src/config.rs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,7 @@ impl SwitchWithOptPath {
347347
pub enum SymbolManglingVersion {
348348
Legacy,
349349
V0,
350+
Hashed,
350351
}
351352

352353
#[derive(Clone, Copy, Debug, PartialEq, Hash)]
@@ -2689,17 +2690,37 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
26892690

26902691
// Check for unstable values of `-C symbol-mangling-version`.
26912692
// This is what prevents them from being used on stable compilers.
2692-
match cg.symbol_mangling_version {
2693-
// Stable values:
2694-
None | Some(SymbolManglingVersion::V0) => {}
2695-
// Unstable values:
2696-
Some(SymbolManglingVersion::Legacy) => {
2693+
match (cg.symbol_mangling_version, unstable_opts.symbol_mangling_version) {
2694+
(Some(smv_c), Some(smv_z)) if smv_c != smv_z => {
2695+
early_dcx.early_fatal(
2696+
"incompatible values passed for `-C symbol-mangling-version` \
2697+
and `-Z symbol-mangling-version`",
2698+
);
2699+
}
2700+
2701+
(Some(SymbolManglingVersion::Legacy), _) => {
26972702
if !unstable_opts.unstable_options {
26982703
early_dcx.early_fatal(
26992704
"`-C symbol-mangling-version=legacy` requires `-Z unstable-options`",
27002705
);
27012706
}
27022707
}
2708+
(Some(SymbolManglingVersion::Hashed), _) => {
2709+
if !unstable_opts.unstable_options {
2710+
early_dcx.early_fatal(
2711+
"`-C symbol-mangling-version=hashed` requires `-Z unstable-options`",
2712+
);
2713+
}
2714+
}
2715+
2716+
// Stable values:
2717+
(Some(SymbolManglingVersion::V0), _) => {}
2718+
(None, None) => {}
2719+
2720+
// Unstable values:
2721+
(None, smv) => {
2722+
cg.symbol_mangling_version = smv;
2723+
}
27032724
}
27042725

27052726
// Check for unstable values of `-C instrument-coverage`.
@@ -2741,6 +2762,12 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
27412762
);
27422763
}
27432764
Some(SymbolManglingVersion::V0) => {}
2765+
Some(SymbolManglingVersion::Hashed) => {
2766+
early_dcx.early_warn(
2767+
"-C instrument-coverage requires symbol mangling version `v0`, \
2768+
but `-Z symbol-mangling-version=hashed` was specified",
2769+
);
2770+
}
27442771
}
27452772
}
27462773

compiler/rustc_session/src/options.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,8 @@ mod desc {
406406
pub const parse_switch_with_opt_path: &str =
407407
"an optional path to the profiling data output directory";
408408
pub const parse_merge_functions: &str = "one of: `disabled`, `trampolines`, or `aliases`";
409-
pub const parse_symbol_mangling_version: &str = "either `legacy` or `v0` (RFC 2603)";
409+
pub const parse_symbol_mangling_version: &str =
410+
"one of: `legacy`, `v0` (RFC 2603), or `hashed`";
410411
pub const parse_src_file_hash: &str = "either `md5` or `sha1`";
411412
pub const parse_relocation_model: &str =
412413
"one of supported relocation models (`rustc --print relocation-models`)";
@@ -1179,6 +1180,7 @@ mod parse {
11791180
*slot = match v {
11801181
Some("legacy") => Some(SymbolManglingVersion::Legacy),
11811182
Some("v0") => Some(SymbolManglingVersion::V0),
1183+
Some("hashed") => Some(SymbolManglingVersion::Hashed),
11821184
_ => return false,
11831185
};
11841186
true
@@ -1490,7 +1492,7 @@ options! {
14901492
"tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"),
14911493
symbol_mangling_version: Option<SymbolManglingVersion> = (None,
14921494
parse_symbol_mangling_version, [TRACKED],
1493-
"which mangling version to use for symbol names ('legacy' (default) or 'v0')"),
1495+
"which mangling version to use for symbol names ('legacy' (default), 'v0', or 'hashed')"),
14941496
target_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
14951497
"select target processor (`rustc --print target-cpus` for details)"),
14961498
target_feature: String = (String::new(), parse_target_feature, [TRACKED],
@@ -1880,6 +1882,9 @@ written to standard error output)"),
18801882
"prefer dynamic linking to static linking for staticlibs (default: no)"),
18811883
strict_init_checks: bool = (false, parse_bool, [TRACKED],
18821884
"control if mem::uninitialized and mem::zeroed panic on more UB"),
1885+
symbol_mangling_version: Option<SymbolManglingVersion> = (None,
1886+
parse_symbol_mangling_version, [TRACKED],
1887+
"which mangling version to use for symbol names ('legacy' (default), 'v0', or 'hashed')"),
18831888
#[rustc_lint_opt_deny_field_access("use `Session::teach` instead of this field")]
18841889
teach: bool = (false, parse_bool, [TRACKED],
18851890
"show extended diagnostic help (default: no)"),
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
2+
use rustc_hir::def_id::CrateNum;
3+
use rustc_middle::ty::{Instance, TyCtxt};
4+
5+
pub(super) fn mangle<'tcx>(
6+
tcx: TyCtxt<'tcx>,
7+
instance: Instance<'tcx>,
8+
instantiating_crate: Option<CrateNum>,
9+
full_mangling_name: impl FnOnce() -> String,
10+
) -> String {
11+
// A generic function of an upstream library can be included in a dylib that depends on it.
12+
// In this case, `instantiating-crate name` is used to replace `crate name`.
13+
// If hash conflicats with other APIs in dylib, the method can be detected immediately.
14+
// Based on `instantiating-crate name`, symbol conflicts with other dylibs are avoided.
15+
let crate_num =
16+
if let Some(krate) = instantiating_crate { krate } else { instance.def_id().krate };
17+
let crate_name = tcx.crate_name(crate_num);
18+
let crate_name = crate_name.as_str();
19+
20+
let hash = tcx.with_stable_hashing_context(|mut hcx| {
21+
let mut hasher = StableHasher::new();
22+
full_mangling_name().hash_stable(&mut hcx, &mut hasher);
23+
hasher.finish::<Hash64>().as_u64()
24+
});
25+
26+
format!("_RNxC{}{crate_name}17H{hash:016x}", crate_name.len())
27+
}

compiler/rustc_symbol_mangling/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ use rustc_middle::query::Providers;
111111
use rustc_middle::ty::{self, Instance, TyCtxt};
112112
use rustc_session::config::SymbolManglingVersion;
113113

114+
mod hashed;
114115
mod legacy;
115116
mod v0;
116117

@@ -265,6 +266,9 @@ fn compute_symbol_name<'tcx>(
265266
let symbol = match mangling_version {
266267
SymbolManglingVersion::Legacy => legacy::mangle(tcx, instance, instantiating_crate),
267268
SymbolManglingVersion::V0 => v0::mangle(tcx, instance, instantiating_crate),
269+
SymbolManglingVersion::Hashed => hashed::mangle(tcx, instance, instantiating_crate, || {
270+
v0::mangle(tcx, instance, instantiating_crate)
271+
}),
268272
};
269273

270274
debug_assert!(
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# ignore-cross-compile
2+
include ../tools.mk
3+
4+
# ignore-windows-msvc
5+
6+
NM=nm -D
7+
RLIB_NAME=liba_rlib.rlib
8+
DYLIB_NAME=liba_dylib.so
9+
SO_NAME=libb_dylib.so
10+
BIN_NAME=b_bin
11+
12+
ifeq ($(UNAME),Darwin)
13+
NM=nm -gU
14+
RLIB_NAME=liba_rlib.rlib
15+
DYLIB_NAME=liba_dylib.dylib
16+
SO_NAME=libb_dylib.dylib
17+
BIN_NAME=b_bin
18+
endif
19+
20+
ifdef IS_WINDOWS
21+
NM=nm -g
22+
RLIB_NAME=liba_rlib.dll.a
23+
DYLIB_NAME=liba_dylib.dll
24+
SO_NAME=libb_dylib.dll
25+
BIN_NAME=b_bin.exe
26+
endif
27+
28+
all:
29+
$(RUSTC) -C prefer-dynamic -Z symbol-mangling-version=hashed -C metadata=foo a_dylib.rs
30+
$(RUSTC) -C prefer-dynamic -Z symbol-mangling-version=hashed -C metadata=bar a_rlib.rs
31+
$(RUSTC) -C prefer-dynamic -L $(TMPDIR) b_dylib.rs
32+
$(RUSTC) -C prefer-dynamic -L $(TMPDIR) b_bin.rs
33+
34+
# Check hashed symbol name
35+
36+
[ "$$($(NM) $(TMPDIR)/$(DYLIB_NAME) | grep -c hello)" -eq "0" ]
37+
[ "$$($(NM) $(TMPDIR)/$(DYLIB_NAME) | grep a_dylib17H | grep -c ' T ')" -eq "1" ]
38+
39+
[ "$$($(NM) $(TMPDIR)/$(SO_NAME) | grep b_dylib | grep -c hello)" -eq "1" ]
40+
[ "$$($(NM) $(TMPDIR)/$(SO_NAME) | grep a_rlib17H | grep -c ' T ')" -eq "1" ]
41+
[ "$$($(NM) $(TMPDIR)/$(SO_NAME) | grep a_dylib17H | grep -c ' U ')" -eq "1" ]
42+
43+
[ "$$($(NM) $(TMPDIR)/$(BIN_NAME) | grep a_rlib17H | grep -c ' U ')" -eq "1" ]
44+
[ "$$($(NM) $(TMPDIR)/$(BIN_NAME) | grep a_dylib17H | grep -c ' U ')" -eq "1" ]
45+
[ "$$($(NM) $(TMPDIR)/$(BIN_NAME) | grep b_dylib | grep hello | grep -c ' U ')" -eq "1" ]
46+
47+
$(call RUN,$(BIN_NAME))
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#![crate_type="dylib"]
2+
pub fn hello() {
3+
println!("hello dylib");
4+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#![crate_type="rlib"]
2+
3+
pub fn hello() {
4+
println!("hello rlib");
5+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
extern crate a_rlib;
2+
extern crate a_dylib;
3+
extern crate b_dylib;
4+
5+
fn main() {
6+
a_rlib::hello();
7+
a_dylib::hello();
8+
b_dylib::hello();
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#![crate_type="dylib"]
2+
3+
extern crate a_rlib;
4+
extern crate a_dylib;
5+
6+
pub fn hello() {
7+
a_rlib::hello();
8+
a_dylib::hello();
9+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
error: incorrect value `bad-value` for codegen option `symbol-mangling-version` - either `legacy` or `v0` (RFC 2603) was expected
1+
error: incorrect value `bad-value` for codegen option `symbol-mangling-version` - one of: `legacy`, `v0` (RFC 2603), or `hashed` was expected
22

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
error: incorrect value `` for codegen option `symbol-mangling-version` - either `legacy` or `v0` (RFC 2603) was expected
1+
error: incorrect value `` for codegen option `symbol-mangling-version` - one of: `legacy`, `v0` (RFC 2603), or `hashed` was expected
22

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
error: codegen option `symbol-mangling-version` requires either `legacy` or `v0` (RFC 2603) (C symbol-mangling-version=<value>)
1+
error: codegen option `symbol-mangling-version` requires one of: `legacy`, `v0` (RFC 2603), or `hashed` (C symbol-mangling-version=<value>)
22

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
error: `-C symbol-mangling-version=hashed` requires `-Z unstable-options`
2+
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
// revisions: legacy legacy-ok
1+
// revisions: legacy legacy-ok hashed hashed-ok
22
// [legacy] compile-flags: -Csymbol-mangling-version=legacy
33
// [legacy-ok] check-pass
44
// [legacy-ok] compile-flags: -Zunstable-options -Csymbol-mangling-version=legacy
5+
// [hashed] compile-flags: -Csymbol-mangling-version=hashed
6+
// [hashed-ok] check-pass
7+
// [hashed-ok] compile-flags: -Zunstable-options -Csymbol-mangling-version=hashed
58

69
fn main() {}

0 commit comments

Comments
 (0)