Skip to content

Commit 6848ab8

Browse files
committed
rewrite symbol-visibility to rmake
1 parent d3dd34a commit 6848ab8

File tree

5 files changed

+171
-124
lines changed

5 files changed

+171
-124
lines changed

src/tools/compiletest/src/command-list.rs

+1
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
117117
"ignore-watchos",
118118
"ignore-windows",
119119
"ignore-windows-gnu",
120+
"ignore-windows-msvc",
120121
"ignore-x32",
121122
"ignore-x86",
122123
"ignore-x86_64",

src/tools/run-make-support/src/command.rs

+2
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,13 @@ pub struct CompletedProcess {
162162

163163
impl CompletedProcess {
164164
#[must_use]
165+
#[track_caller]
165166
pub fn stdout_utf8(&self) -> String {
166167
String::from_utf8(self.output.stdout.clone()).expect("stdout is not valid UTF-8")
167168
}
168169

169170
#[must_use]
171+
#[track_caller]
170172
pub fn stderr_utf8(&self) -> String {
171173
String::from_utf8(self.output.stderr.clone()).expect("stderr is not valid UTF-8")
172174
}

src/tools/tidy/src/allowed_run_make_makefiles.txt

-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,6 @@ run-make/staticlib-blank-lib/Makefile
125125
run-make/staticlib-dylib-linkage/Makefile
126126
run-make/std-core-cycle/Makefile
127127
run-make/symbol-mangling-hashed/Makefile
128-
run-make/symbol-visibility/Makefile
129128
run-make/sysroot-crates-are-unstable/Makefile
130129
run-make/test-benches/Makefile
131130
run-make/thumb-none-cortex-m/Makefile

tests/run-make/symbol-visibility/Makefile

-123
This file was deleted.
+168
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
// Dynamic libraries on Rust used to export a very high amount of symbols,
2+
// going as far as filling the output with mangled names and generic function
3+
// names. After the rework of #38117, this test checks that no mangled Rust symbols
4+
// are exported, and that generics are only shown if explicitely requested.
5+
// See https://github.com./rust-lang/rust/issues/37530
6+
7+
//@ ignore-windows-msvc
8+
9+
use run_make_support::{bin_name, dynamic_lib_name, is_windows, llvm_readobj, regex, rustc};
10+
11+
fn main() {
12+
let mut cdylib_name = dynamic_lib_name("a_cdylib");
13+
let mut rdylib_name = dynamic_lib_name("a_rust_dylib");
14+
let exe_name = bin_name("an_executable");
15+
let mut combined_cdylib_name = dynamic_lib_name("combined_rlib_dylib");
16+
rustc().arg("-Zshare-generics=no").input("an_rlib.rs").run();
17+
rustc().arg("-Zshare-generics=no").input("a_cdylib.rs").run();
18+
rustc().arg("-Zshare-generics=no").input("a_rust_dylib.rs").run();
19+
rustc().arg("-Zshare-generics=no").input("a_proc_macro.rs").run();
20+
rustc().arg("-Zshare-generics=no").input("an_executable.rs").run();
21+
rustc()
22+
.arg("-Zshare-generics=no")
23+
.input("a_cdylib.rs")
24+
.crate_name("combined_rlib_dylib")
25+
.crate_type("rlib,cdylib")
26+
.run();
27+
28+
// Check that a cdylib exports its public #[no_mangle] functions
29+
symbols_check(&cdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_cdylib"), true);
30+
// Check that a cdylib exports the public #[no_mangle] functions of dependencies
31+
symbols_check(&cdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), true);
32+
// Check that a cdylib DOES NOT export any public Rust functions
33+
symbols_check(&cdylib_name, SymbolCheckType::AnyRustSymbol, false);
34+
35+
// Check that a Rust dylib exports its monomorphic functions
36+
symbols_check(
37+
&rdylib_name,
38+
SymbolCheckType::StrSymbol("public_c_function_from_rust_dylib"),
39+
true,
40+
);
41+
symbols_check(
42+
&rdylib_name,
43+
SymbolCheckType::StrSymbol("public_rust_function_from_rust_dylib"),
44+
true,
45+
);
46+
// Check that a Rust dylib does not export generics if -Zshare-generics=no
47+
symbols_check(
48+
&rdylib_name,
49+
SymbolCheckType::StrSymbol("public_generic_function_from_rust_dylib"),
50+
false,
51+
);
52+
53+
// Check that a Rust dylib exports the monomorphic functions from its dependencies
54+
symbols_check(&rdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), true);
55+
symbols_check(&rdylib_name, SymbolCheckType::StrSymbol("public_rust_function_from_rlib"), true);
56+
// Check that a Rust dylib does not export generics if -Zshare-generics=no
57+
symbols_check(
58+
&rdylib_name,
59+
SymbolCheckType::StrSymbol("public_generic_function_from_rlib"),
60+
false,
61+
);
62+
63+
// FIXME(nbdd0121): This is broken in MinGW, see https://github.com./rust-lang/rust/pull/95604#issuecomment-1101564032
64+
// if is_windows() {
65+
// // Check that an executable does not export any dynamic symbols
66+
// symbols_check(&exe_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib")
67+
//, false);
68+
// symbols_check(
69+
// &exe_name,
70+
// SymbolCheckType::StrSymbol("public_rust_function_from_exe"),
71+
// false,
72+
// );
73+
// }
74+
75+
// Check the combined case, where we generate a cdylib and an rlib in the same
76+
// compilation session:
77+
// Check that a cdylib exports its public //[no_mangle] functions
78+
symbols_check(
79+
&combined_cdylib_name,
80+
SymbolCheckType::StrSymbol("public_c_function_from_cdylib"),
81+
true,
82+
);
83+
// Check that a cdylib exports the public //[no_mangle] functions of dependencies
84+
symbols_check(
85+
&combined_cdylib_name,
86+
SymbolCheckType::StrSymbol("public_c_function_from_rlib"),
87+
true,
88+
);
89+
// Check that a cdylib DOES NOT export any public Rust functions
90+
symbols_check(&combined_cdylib_name, SymbolCheckType::AnyRustSymbol, false);
91+
92+
rustc().arg("-Zshare-generics=yes").input("an_rlib.rs").run();
93+
rustc().arg("-Zshare-generics=yes").input("a_cdylib.rs").run();
94+
rustc().arg("-Zshare-generics=yes").input("a_rust_dylib.rs").run();
95+
rustc().arg("-Zshare-generics=yes").input("an_executable.rs").run();
96+
97+
// Check that a cdylib exports its public //[no_mangle] functions
98+
symbols_check(&cdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_cdylib"), true);
99+
// Check that a cdylib exports the public //[no_mangle] functions of dependencies
100+
symbols_check(&cdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), true);
101+
// Check that a cdylib DOES NOT export any public Rust functions
102+
symbols_check(&cdylib_name, SymbolCheckType::AnyRustSymbol, false);
103+
104+
// Check that a Rust dylib exports its monomorphic functions, including generics this time
105+
symbols_check(
106+
&rdylib_name,
107+
SymbolCheckType::StrSymbol("public_c_function_from_rust_dylib"),
108+
true,
109+
);
110+
symbols_check(
111+
&rdylib_name,
112+
SymbolCheckType::StrSymbol("public_rust_function_from_rust_dylib"),
113+
true,
114+
);
115+
symbols_check(
116+
&rdylib_name,
117+
SymbolCheckType::StrSymbol("public_generic_function_from_rust_dylib"),
118+
true,
119+
);
120+
121+
// Check that a Rust dylib exports the monomorphic functions from its dependencies
122+
symbols_check(&rdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), true);
123+
symbols_check(&rdylib_name, SymbolCheckType::StrSymbol("public_rust_function_from_rlib"), true);
124+
symbols_check(
125+
&rdylib_name,
126+
SymbolCheckType::StrSymbol("public_generic_function_from_rlib"),
127+
true,
128+
);
129+
130+
// FIXME(nbdd0121): This is broken in MinGW, see https://github.com./rust-lang/rust/pull/95604#issuecomment-1101564032
131+
// if is_windows() {
132+
// // Check that an executable does not export any dynamic symbols
133+
// symbols_check(&exe_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib")
134+
//, false);
135+
// symbols_check(
136+
// &exe_name,
137+
// SymbolCheckType::StrSymbol("public_rust_function_from_exe"),
138+
// false,
139+
// );
140+
// }
141+
}
142+
143+
#[track_caller]
144+
fn symbols_check(path: &str, symbol_check_type: SymbolCheckType, exists_once: bool) {
145+
let out = llvm_readobj().arg("--dyn-symbols").input(path).run().stdout_utf8();
146+
assert_eq!(
147+
out.lines()
148+
.filter(|&line| !line.contains("__imp_") && has_symbol(line, symbol_check_type))
149+
.count()
150+
== 1,
151+
exists_once
152+
);
153+
}
154+
155+
fn has_symbol(line: &str, symbol_check_type: SymbolCheckType) -> bool {
156+
if let SymbolCheckType::StrSymbol(expected) = symbol_check_type {
157+
line.contains(expected)
158+
} else {
159+
let regex = regex::Regex::new(r#"_ZN.*h.*E\|_R[a-zA-Z0-9_]+"#).unwrap();
160+
regex.is_match(line)
161+
}
162+
}
163+
164+
#[derive(Clone, Copy)]
165+
enum SymbolCheckType {
166+
StrSymbol(&'static str),
167+
AnyRustSymbol,
168+
}

0 commit comments

Comments
 (0)