Skip to content

Commit

Permalink
Auto merge of rust-lang#135458 - jieyouxu:migrate-extern-fn-reachable…
Browse files Browse the repository at this point in the history
…, 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
bors committed Jan 14, 2025
2 parents 2ae9916 + 1332c85 commit c0a7d85
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 27 deletions.
1 change: 0 additions & 1 deletion src/tools/tidy/src/allowed_run_make_makefiles.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
run-make/cat-and-grep-sanity-check/Makefile
run-make/extern-fn-reachable/Makefile
run-make/jobserver-error/Makefile
run-make/split-debuginfo/Makefile
run-make/symbol-mangling-hashed/Makefile
Expand Down
26 changes: 0 additions & 26 deletions tests/run-make/extern-fn-reachable/Makefile

This file was deleted.

15 changes: 15 additions & 0 deletions tests/run-make/extern-fn-reachable/dylib.rs
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() {}
55 changes: 55 additions & 0 deletions tests/run-make/extern-fn-reachable/rmake.rs
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);
}

0 comments on commit c0a7d85

Please sign in to comment.