| 
 | 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 | +// FIXME(Oneirical): This may work without ignore-windows-msvc and ignore-cross-compile  | 
 | 8 | + | 
 | 9 | +use run_make_support::{bin_name, dynamic_lib_name, is_windows, llvm_readobj, regex, rustc};  | 
 | 10 | + | 
 | 11 | +fn main() {  | 
 | 12 | +    let cdylib_name = dynamic_lib_name("a_cdylib");  | 
 | 13 | +    let rdylib_name = dynamic_lib_name("a_rust_dylib");  | 
 | 14 | +    let exe_name = bin_name("an_executable");  | 
 | 15 | +    let 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"), 2);  | 
 | 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"), 2);  | 
 | 32 | +    // Check that a cdylib DOES NOT export any public Rust functions  | 
 | 33 | +    symbols_check(&cdylib_name, SymbolCheckType::AnyRustSymbol, 0);  | 
 | 34 | + | 
 | 35 | +    // Check that a Rust dylib exports its monomorphic functions  | 
 | 36 | +    symbols_check(&rdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_rust_dylib"), 2);  | 
 | 37 | +    symbols_check(  | 
 | 38 | +        &rdylib_name,  | 
 | 39 | +        SymbolCheckType::StrSymbol("public_rust_function_from_rust_dylib"),  | 
 | 40 | +        2,  | 
 | 41 | +    );  | 
 | 42 | +    // Check that a Rust dylib does not export generics if -Zshare-generics=no  | 
 | 43 | +    symbols_check(  | 
 | 44 | +        &rdylib_name,  | 
 | 45 | +        SymbolCheckType::StrSymbol("public_generic_function_from_rust_dylib"),  | 
 | 46 | +        1,  | 
 | 47 | +    );  | 
 | 48 | + | 
 | 49 | +    // Check that a Rust dylib exports the monomorphic functions from its dependencies  | 
 | 50 | +    symbols_check(&rdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), 2);  | 
 | 51 | +    symbols_check(&rdylib_name, SymbolCheckType::StrSymbol("public_rust_function_from_rlib"), 2);  | 
 | 52 | +    // Check that a Rust dylib does not export generics if -Zshare-generics=no  | 
 | 53 | +    symbols_check(&rdylib_name, SymbolCheckType::StrSymbol("public_generic_function_from_rlib"), 1);  | 
 | 54 | + | 
 | 55 | +    if is_windows() {  | 
 | 56 | +        // Check that an executable does not export any dynamic symbols  | 
 | 57 | +        symbols_check(&exe_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), 0);  | 
 | 58 | +        symbols_check(&exe_name, SymbolCheckType::StrSymbol("public_rust_function_from_exe"), 0);  | 
 | 59 | +    }  | 
 | 60 | + | 
 | 61 | +    // Check the combined case, where we generate a cdylib and an rlib in the same  | 
 | 62 | +    // compilation session:  | 
 | 63 | +    // Check that a cdylib exports its public //[no_mangle] functions  | 
 | 64 | +    symbols_check(  | 
 | 65 | +        &combined_cdylib_name,  | 
 | 66 | +        SymbolCheckType::StrSymbol("public_c_function_from_cdylib"),  | 
 | 67 | +        2,  | 
 | 68 | +    );  | 
 | 69 | +    // Check that a cdylib exports the public //[no_mangle] functions of dependencies  | 
 | 70 | +    symbols_check(  | 
 | 71 | +        &combined_cdylib_name,  | 
 | 72 | +        SymbolCheckType::StrSymbol("public_c_function_from_rlib"),  | 
 | 73 | +        2,  | 
 | 74 | +    );  | 
 | 75 | +    // Check that a cdylib DOES NOT export any public Rust functions  | 
 | 76 | +    symbols_check(&combined_cdylib_name, SymbolCheckType::AnyRustSymbol, 0);  | 
 | 77 | + | 
 | 78 | +    rustc().arg("-Zshare-generics=yes").input("an_rlib.rs").run();  | 
 | 79 | +    rustc().arg("-Zshare-generics=yes").input("a_cdylib.rs").run();  | 
 | 80 | +    rustc().arg("-Zshare-generics=yes").input("a_rust_dylib.rs").run();  | 
 | 81 | +    rustc().arg("-Zshare-generics=yes").input("an_executable.rs").run();  | 
 | 82 | + | 
 | 83 | +    // Check that a cdylib exports its public //[no_mangle] functions  | 
 | 84 | +    symbols_check(&cdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_cdylib"), 2);  | 
 | 85 | +    // Check that a cdylib exports the public //[no_mangle] functions of dependencies  | 
 | 86 | +    symbols_check(&cdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), 2);  | 
 | 87 | +    // Check that a cdylib DOES NOT export any public Rust functions  | 
 | 88 | +    symbols_check(&cdylib_name, SymbolCheckType::AnyRustSymbol, 0);  | 
 | 89 | + | 
 | 90 | +    // Check that a Rust dylib exports its monomorphic functions, including generics this time  | 
 | 91 | +    symbols_check(&rdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_rust_dylib"), 2);  | 
 | 92 | +    symbols_check(  | 
 | 93 | +        &rdylib_name,  | 
 | 94 | +        SymbolCheckType::StrSymbol("public_rust_function_from_rust_dylib"),  | 
 | 95 | +        2,  | 
 | 96 | +    );  | 
 | 97 | +    symbols_check(  | 
 | 98 | +        &rdylib_name,  | 
 | 99 | +        SymbolCheckType::StrSymbol("public_generic_function_from_rust_dylib"),  | 
 | 100 | +        2,  | 
 | 101 | +    );  | 
 | 102 | + | 
 | 103 | +    // Check that a Rust dylib exports the monomorphic functions from its dependencies  | 
 | 104 | +    symbols_check(&rdylib_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), 2);  | 
 | 105 | +    symbols_check(&rdylib_name, SymbolCheckType::StrSymbol("public_rust_function_from_rlib"), 2);  | 
 | 106 | +    symbols_check(&rdylib_name, SymbolCheckType::StrSymbol("public_generic_function_from_rlib"), 2);  | 
 | 107 | + | 
 | 108 | +    if is_windows() {  | 
 | 109 | +        // Check that an executable does not export any dynamic symbols  | 
 | 110 | +        symbols_check(&exe_name, SymbolCheckType::StrSymbol("public_c_function_from_rlib"), 0);  | 
 | 111 | +        symbols_check(&exe_name, SymbolCheckType::StrSymbol("public_rust_function_from_exe"), 0);  | 
 | 112 | +    }  | 
 | 113 | +}  | 
 | 114 | + | 
 | 115 | +#[track_caller]  | 
 | 116 | +fn symbols_check(path: &str, symbol_check_type: SymbolCheckType, count: usize) {  | 
 | 117 | +    let out = llvm_readobj().arg("--symbols").input(path).run().stdout_utf8();  | 
 | 118 | +    assert_eq!(  | 
 | 119 | +        out.lines()  | 
 | 120 | +            .filter(|&line| !line.contains("__imp_") && has_symbol(line, symbol_check_type))  | 
 | 121 | +            .count(),  | 
 | 122 | +        count  | 
 | 123 | +    );  | 
 | 124 | +}  | 
 | 125 | + | 
 | 126 | +fn has_symbol(line: &str, symbol_check_type: SymbolCheckType) -> bool {  | 
 | 127 | +    if let SymbolCheckType::StrSymbol(expected) = symbol_check_type {  | 
 | 128 | +        line.contains(expected)  | 
 | 129 | +    } else {  | 
 | 130 | +        let regex = regex::Regex::new(r#"_ZN.*h.*E\|_R[a-zA-Z0-9_]+"#).unwrap();  | 
 | 131 | +        regex.is_match(line)  | 
 | 132 | +    }  | 
 | 133 | +}  | 
 | 134 | + | 
 | 135 | +#[derive(Clone, Copy)]  | 
 | 136 | +enum SymbolCheckType {  | 
 | 137 | +    StrSymbol(&'static str),  | 
 | 138 | +    AnyRustSymbol,  | 
 | 139 | +}  | 
0 commit comments