Skip to content

Commit cd8beab

Browse files
committed
Auto merge of rust-lang#135768 - jieyouxu:migrate-symbol-mangling-hashed, r=<try>
tests: Port `symbol-mangling-hashed` to rmake.rs Part of rust-lang#121876. This PR supersedes rust-lang#128567 and is co-authored with `@lolbinarycat.` ### Summary This PR ports `tests/run-make/symbol-mangling-hashed` to rmake.rs. Notable differences when compared to the Makefile version includes: - It's no longer limited to linux + x86_64 only. In particular, this now is exercised on darwin and windows (esp. msvc) too. - The test uses `object` crate to be more precise in the filtering, and avoids relying on parsing the human-readable `nm` output for *some* `nm` in the given environment (which isn't really a thing on msvc anyway, and `llvm-nm` doesn't handle msvc dylibs AFAICT). - Dump the symbols satisfying various criteria on test failure to make it hopefully less of a pain to debug if it ever fails in CI. ### Review advice - Best reviewed commit-by-commit. - I'm not *super* sure about the msvc logic, would benefit from a MSVC (PE/COFF) expert taking a look. --- try-job: x86_64-msvc try-job: i686-msvc try-job: i686-mingw try-job: x86_64-mingw-1 try-job: x86_64-apple-1 try-job: aarch64-apple try-job: test-various
2 parents b5741a3 + 10841e5 commit cd8beab

File tree

7 files changed

+360
-57
lines changed

7 files changed

+360
-57
lines changed

src/tools/run-make-support/src/external_deps/rustc.rs

+12
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,18 @@ impl Rustc {
215215
self
216216
}
217217

218+
/// Specify option of `-C symbol-mangling-version`.
219+
pub fn symbol_mangling_version(&mut self, option: &str) -> &mut Self {
220+
self.cmd.arg(format!("-Csymbol-mangling-version={option}"));
221+
self
222+
}
223+
224+
/// Specify `-C prefer-dynamic`.
225+
pub fn prefer_dynamic(&mut self) -> &mut Self {
226+
self.cmd.arg(format!("-Cprefer-dynamic"));
227+
self
228+
}
229+
218230
/// Specify error format to use
219231
pub fn error_format(&mut self, format: &str) -> &mut Self {
220232
self.cmd.arg(format!("--error-format={format}"));

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

+7-3
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ pub use wasmparser;
4747
// tidy-alphabetical-end
4848

4949
// Re-exports of external dependencies.
50-
pub use external_deps::{c_build, c_cxx_compiler, clang, htmldocck, llvm, python, rustc, rustdoc};
50+
pub use external_deps::{
51+
cargo, c_build, c_cxx_compiler, clang, htmldocck, llvm, python, rustc, rustdoc
52+
};
5153

5254
// These rely on external dependencies.
5355
pub use c_cxx_compiler::{Cc, Gcc, cc, cxx, extra_c_flags, extra_cxx_flags, gcc};
@@ -79,7 +81,10 @@ pub use env::{env_var, env_var_os, set_current_dir};
7981
pub use run::{cmd, run, run_fail, run_with_args};
8082

8183
/// Helpers for checking target information.
82-
pub use targets::{is_aix, is_darwin, is_msvc, is_windows, llvm_components_contain, target, uname, apple_os};
84+
pub use targets::{
85+
apple_os, is_aix, is_darwin, is_msvc, is_windows, is_windows_gnu, llvm_components_contain,
86+
target, uname,
87+
};
8388

8489
/// Helpers for building names of output artifacts that are potentially target-specific.
8590
pub use artifact_names::{
@@ -104,4 +109,3 @@ pub use assertion_helpers::{
104109
pub use string::{
105110
count_regex_matches_in_files_with_extension, invalid_utf8_contains, invalid_utf8_not_contains,
106111
};
107-
use crate::external_deps::cargo;

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

+71-5
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,84 @@
11
use std::path::Path;
22

3-
use object::{self, Object, ObjectSymbol, SymbolIterator};
3+
use object::{self, Object, ObjectSymbol, SectionIndex, SymbolIterator};
44

5-
/// Iterate through the symbols in an object file.
5+
/// Given an [`object::File`], find the dynamic symbol names via
6+
/// [`object::Object::dynamic_symbols`]. This does **not** impose any filters on the specific
7+
/// dynamic symbols, e.g. if they are global or local, if they are defined or not, and in which
8+
/// section the dynamic symbols reside in.
69
///
7-
/// Uses a callback because `SymbolIterator` does not own its data.
10+
/// On Windows, [`object::Object::dynamic_symbols`] will return an empty iterator because the symbol
11+
/// names are stored in a separate file (which object doesn't know how to read). Use
12+
/// [`object::Object::exports`] instead of this helper.
13+
#[track_caller]
14+
pub fn dynamic_symbol_names<'file>(file: &'file object::File<'file>) -> Vec<&'file str> {
15+
file.dynamic_symbols().map(|sym| sym.name().unwrap()).collect()
16+
}
17+
18+
/// Given an [`object::File`], find the global (externally visible) dynamic symbol names in the
19+
/// `.text` section via [`object::Object::dynamic_symbols`]. This requires that `.text`'s section
20+
/// index is known.
21+
///
22+
/// On Windows, [`object::Object::dynamic_symbols`] will return an empty iterator because the symbol
23+
/// names are stored in a separate file (which object doesn't know how to read). Use
24+
/// [`object::Object::exports`] instead of this helper.
25+
///
26+
/// # Example
27+
///
28+
/// ```rust,no_run
29+
/// use object::{self, Object};
30+
/// use run_make_support::{rfs, dynamic_lib_name};
31+
///
32+
/// let dylib_filename = dynamic_lib_name("foo");
33+
/// let blob = rfs::read(&dylib_filename);
34+
/// let file = object::File::parse(&*blob)
35+
/// .unwrap_or_else(|e| panic!("failed to read `{dylib_filename}`: {e}"));
36+
/// let text_section =
37+
/// file.section_by_name(".text").expect("couldn't find `.text` section");
38+
/// let found_symbols = text_section_global_dynamic_symbol_names(&file, text_section.index());
39+
/// ```
40+
#[track_caller]
41+
pub fn text_section_global_dynamic_symbol_names<'file>(
42+
file: &'file object::File<'file>,
43+
text_section_idx: SectionIndex,
44+
) -> Vec<&'file str> {
45+
file.dynamic_symbols()
46+
.filter(|sym| {
47+
sym.is_global() && sym.section_index().is_some_and(|idx| idx == text_section_idx)
48+
})
49+
.map(|sym| sym.name().unwrap())
50+
.collect()
51+
}
52+
53+
/// Given an [`object::File`], find the global (externally visible) undefined dynamic symbol names
54+
/// in the `.text` section via [`object::Object::dynamic_symbols`].
55+
///
56+
/// On Windows, [`object::Object::dynamic_symbols`] will return an empty iterator because the symbol
57+
/// names are stored in a separate file (which object doesn't know how to read). Use
58+
/// [`object::Object::exports`] instead of this helper.
59+
#[track_caller]
60+
pub fn global_undefined_dynamic_symbol_names<'file>(
61+
file: &'file object::File<'file>,
62+
) -> Vec<&'file str> {
63+
file.dynamic_symbols()
64+
.filter(|sym| sym.is_global() && sym.is_undefined())
65+
.map(|sym| sym.name().unwrap())
66+
.collect()
67+
}
68+
69+
/// Iterate through the symbols in an object file. See [`object::Object::symbols`].
870
///
971
/// Panics if `path` is not a valid object file readable by the current user.
72+
#[track_caller]
1073
pub fn with_symbol_iter<P, F, R>(path: P, func: F) -> R
1174
where
1275
P: AsRef<Path>,
1376
F: FnOnce(&mut SymbolIterator<'_, '_>) -> R,
1477
{
15-
let raw_bytes = crate::fs::read(path);
16-
let f = object::File::parse(raw_bytes.as_slice()).expect("unable to parse file");
78+
let path = path.as_ref();
79+
let blob = crate::fs::read(path);
80+
let f = object::File::parse(&*blob)
81+
.unwrap_or_else(|e| panic!("failed to parse `{}`: {e}", path.display()));
1782
let mut iter = f.symbols();
1883
func(&mut iter)
1984
}
@@ -24,6 +89,7 @@ where
2489
/// `path` contain a substring listed in `substrings`.
2590
///
2691
/// Panics if `path` is not a valid object file readable by the current user.
92+
#[track_caller]
2793
pub fn any_symbol_contains(path: impl AsRef<Path>, substrings: &[&str]) -> bool {
2894
with_symbol_iter(path, |syms| {
2995
for sym in syms {

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

+6
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ pub fn is_msvc() -> bool {
2222
target().contains("msvc")
2323
}
2424

25+
/// Check if target is windows-gnu.
26+
#[must_use]
27+
pub fn is_windows_gnu() -> bool {
28+
target().ends_with("windows-gnu")
29+
}
30+
2531
/// Check if target uses macOS.
2632
#[must_use]
2733
pub fn is_darwin() -> bool {
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
run-make/cat-and-grep-sanity-check/Makefile
22
run-make/jobserver-error/Makefile
33
run-make/split-debuginfo/Makefile
4-
run-make/symbol-mangling-hashed/Makefile
54
run-make/translation/Makefile

tests/run-make/symbol-mangling-hashed/Makefile

-48
This file was deleted.

0 commit comments

Comments
 (0)