forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of rust-lang#135458 - jieyouxu:migrate-extern-fn-reachable…
…, r=<try> tests: Port `extern-fn-reachable` to rmake.rs Part of rust-lang#121876. ## Summary This PR ports `tests/run-make/extern-fn-reachable` to use `rmake.rs`. Notable changes: - We now use the `object` crate and look at the exported symbols specifically. - This test's coverage regressed against windows-msvc back in [replace dynamic library module with libloading rust-lang#90716](rust-lang#90716), but since we use `object` now, we're able to claw the test coverage back. - The checks are now stricter: 1. It no longer looks for substring symbol matches in `nm` textual outputs, it inspects the symbol names precisely. 2. We now also explicitly check for the presence of leading underscore in exported symbol names on apple vs non-apple targets. - Added another case of `#[no_mangle] fn fun6() {}` (note the lack of `pub`) to check that Rust nameres visibility is orthogonal to symbol visiblity in dylib. ## History - Test was initially introduced as a run-pass[^run-pass] test as part of [Don't mark reachable extern fns as internal rust-lang#10539](rust-lang#10539). - Test re-introduced as a run-make test in rust-lang#13741. - Later, the test coverage regressed in rust-lang#90716. [^run-pass]: no longer a thing nowadays Supersedes rust-lang#128314. Co-authored with `@lolbinarycat.` r? `@ghost` 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
- Loading branch information
Showing
4 changed files
with
70 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,34 @@ | ||
#![crate_type = "dylib"] | ||
#![allow(dead_code)] | ||
|
||
// `pub` extern fn here is a Rust nameres visibility concept, and should not affect symbol | ||
// visibility in the dylib. | ||
#[no_mangle] | ||
pub extern "C" fn fun1() {} | ||
|
||
// (Lack of) `pub` for the extern fn here is a Rust nameres visibility concept, and should not | ||
// affect symbol visibility in the dylib. | ||
#[no_mangle] | ||
extern "C" fn fun2() {} | ||
|
||
// Modules are a Rust nameres concept, and should not affect symbol visibility in the dylib if the | ||
// extern fn is nested inside a module. | ||
mod foo { | ||
#[no_mangle] | ||
pub extern "C" fn fun3() {} | ||
} | ||
|
||
// Similarly, the Rust visibility of the containing module is a Rust nameres concept, and should not | ||
// affect symbol visibility in the dylib. | ||
pub mod bar { | ||
#[no_mangle] | ||
pub extern "C" fn fun4() {} | ||
} | ||
|
||
// Non-extern `#[no_mangle]` fn should induce a symbol visible in the dylib. | ||
#[no_mangle] | ||
pub fn fun5() {} | ||
|
||
// The Rust visibility of the fn should not affect is symbol visibility in the dylib. | ||
#[no_mangle] | ||
fn fun6() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
//! Smoke test to check that that symbols of `extern "C"` functions and `#[no_mangle]` rust | ||
//! functions: | ||
//! | ||
//! 1. Are externally visible in the dylib produced. | ||
//! 2. That the symbol visibility is orthogonal to the Rust nameres visibility of the functions | ||
//! involved. | ||
//@ ignore-cross-compile | ||
|
||
use run_make_support::object::{self, Object, ObjectSection, ObjectSymbol}; | ||
use run_make_support::{dynamic_lib_name, is_darwin, is_msvc, path, rfs, rustc}; | ||
|
||
fn main() { | ||
let dylib = dynamic_lib_name("dylib"); | ||
rustc().input("dylib.rs").output(&dylib).arg("-Cprefer-dynamic").run(); | ||
let mut fun1_count = 0; // #[no_mangle] pub extern "C" fn fun1() {} | ||
let mut fun2_count = 0; // #[no_mangle] extern "C" fn fun2() {} | ||
let mut fun3_count = 0; // mod foo { #[no_mangle] pub extern "C" fn fun3() {} } | ||
let mut fun4_count = 0; // pub mod bar { #[no_mangle] pub extern "C" fn fun4() {} } | ||
let mut fun5_count = 0; // #[no_mangle] pub fn fun5() {} | ||
let mut fun6_count = 0; // #[no_mangle] fn fun6() {} | ||
|
||
let p = if is_msvc() { path(dylib) } else { path(dylib) }; | ||
let blob = rfs::read(&p); | ||
let file = object::File::parse(&*blob).unwrap(); | ||
|
||
for export in file.exports().unwrap() { | ||
let sym_name = export.name(); | ||
let sym_name = String::from_utf8_lossy(sym_name); | ||
match sym_name.as_ref() { | ||
"fun1" => fun1_count += 1, | ||
"fun2" => fun2_count += 1, | ||
"fun3" => fun3_count += 1, | ||
"fun4" => fun4_count += 1, | ||
"fun5" => fun5_count += 1, | ||
"fun6" => fun6_count += 1, | ||
// Mach-O states that all exported symbols should have an underscore as prefix. At the | ||
// same time dlsym will implicitly add it, so outside of compilers, linkers and people | ||
// writing assembly, nobody needs to be aware of this. | ||
"_fun1" if is_darwin() => fun1_count += 1, | ||
"_fun2" if is_darwin() => fun2_count += 1, | ||
"_fun3" if is_darwin() => fun3_count += 1, | ||
"_fun4" if is_darwin() => fun4_count += 1, | ||
"_fun5" if is_darwin() => fun5_count += 1, | ||
"_fun6" if is_darwin() => fun6_count += 1, | ||
_ => {} | ||
} | ||
} | ||
assert_eq!(fun1_count, 1); | ||
assert_eq!(fun2_count, 1); | ||
assert_eq!(fun3_count, 1); | ||
assert_eq!(fun4_count, 1); | ||
assert_eq!(fun5_count, 1); | ||
assert_eq!(fun6_count, 1); | ||
} |