@@ -11,10 +11,11 @@ use std::{env, fmt, fs, io, mem, str};
1111
1212use find_msvc_tools;
1313use itertools:: Itertools ;
14+ use object:: { Object , ObjectSection , ObjectSymbol } ;
1415use regex:: Regex ;
1516use rustc_arena:: TypedArena ;
1617use rustc_attr_parsing:: eval_config_entry;
17- use rustc_data_structures:: fx:: FxIndexSet ;
18+ use rustc_data_structures:: fx:: { FxHashSet , FxIndexSet } ;
1819use rustc_data_structures:: memmap:: Mmap ;
1920use rustc_data_structures:: temp_dir:: MaybeTempDir ;
2021use rustc_errors:: { DiagCtxtHandle , LintDiagnostic } ;
@@ -2185,6 +2186,76 @@ fn add_rpath_args(
21852186 }
21862187}
21872188
2189+ fn add_c_staticlib_symbols (
2190+ sess : & Session ,
2191+ lib : & NativeLib ,
2192+ out : & mut Vec < ( String , SymbolExportKind ) > ,
2193+ ) -> io:: Result < ( ) > {
2194+ let file_path = find_native_static_library ( lib. name . as_str ( ) , lib. verbatim , sess) ;
2195+
2196+ let archive_map = unsafe { Mmap :: map ( File :: open ( & file_path) ?) ? } ;
2197+
2198+ let archive = object:: read:: archive:: ArchiveFile :: parse ( & * archive_map)
2199+ . map_err ( |e| io:: Error :: new ( io:: ErrorKind :: InvalidData , e) ) ?;
2200+
2201+ for member in archive. members ( ) {
2202+ let member = member. map_err ( |e| io:: Error :: new ( io:: ErrorKind :: InvalidData , e) ) ?;
2203+
2204+ let data = member
2205+ . data ( & * archive_map)
2206+ . map_err ( |e| io:: Error :: new ( io:: ErrorKind :: InvalidData , e) ) ?;
2207+
2208+ // clang LTO: raw LLVM bitcode
2209+ if data. starts_with ( b"BC\xc0 \xde " ) {
2210+ return Err ( io:: Error :: new (
2211+ io:: ErrorKind :: InvalidData ,
2212+ "LLVM bitcode object in C static library (LTO not supported)" ,
2213+ ) ) ;
2214+ }
2215+
2216+ let object = object:: File :: parse ( & * data)
2217+ . map_err ( |e| io:: Error :: new ( io:: ErrorKind :: InvalidData , e) ) ?;
2218+
2219+ // gcc / clang ELF / Mach-O LTO
2220+ if object. sections ( ) . any ( |s| {
2221+ s. name ( ) . map ( |n| n. starts_with ( ".gnu.lto_" ) || n == ".llvm.lto" ) . unwrap_or ( false )
2222+ } ) {
2223+ return Err ( io:: Error :: new (
2224+ io:: ErrorKind :: InvalidData ,
2225+ "LTO object in C static library is not supported" ,
2226+ ) ) ;
2227+ }
2228+
2229+ for symbol in object. symbols ( ) {
2230+ if symbol. scope ( ) != object:: SymbolScope :: Dynamic {
2231+ continue ;
2232+ }
2233+
2234+ let mut name = match symbol. name ( ) {
2235+ Ok ( n) => n,
2236+ Err ( _) => continue ,
2237+ } ;
2238+
2239+ if sess. target . is_like_darwin {
2240+ if let Some ( stripped) = name. strip_prefix ( '_' ) {
2241+ name = stripped;
2242+ }
2243+ }
2244+
2245+ let export_kind = match symbol. kind ( ) {
2246+ object:: SymbolKind :: Text => SymbolExportKind :: Text ,
2247+ object:: SymbolKind :: Data => SymbolExportKind :: Data ,
2248+ _ => continue ,
2249+ } ;
2250+
2251+ // FIXME:The symbol mangle rules are slightly different in 32-bit Windows. Need to be resolved.
2252+ out. push ( ( name. to_string ( ) , export_kind) ) ;
2253+ }
2254+ }
2255+
2256+ Ok ( ( ) )
2257+ }
2258+
21882259/// Produce the linker command line containing linker path and arguments.
21892260///
21902261/// When comments in the function say "order-(in)dependent" they mean order-dependence between
@@ -2217,18 +2288,33 @@ fn linker_with_args(
22172288 ) ;
22182289 let link_output_kind = link_output_kind ( sess, crate_type) ;
22192290
2291+ let mut export_symbols = codegen_results. crate_info . exported_symbols [ & crate_type] . clone ( ) ;
2292+
2293+ if crate_type == CrateType :: Cdylib {
2294+ let mut seen = FxHashSet :: default ( ) ;
2295+
2296+ for lib in codegen_results. crate_info . used_libraries . iter ( ) . filter ( |lib| {
2297+ matches ! ( lib. kind, NativeLibKind :: Static { export_symbols: Some ( true ) , .. } )
2298+ } ) {
2299+ if !seen. insert ( ( lib. name , lib. verbatim ) ) {
2300+ continue ;
2301+ }
2302+
2303+ if let Err ( err) = add_c_staticlib_symbols ( & sess, lib, & mut export_symbols) {
2304+ sess. dcx ( )
2305+ . fatal ( format ! ( "failed to process C static library `{}`: {}" , lib. name, err) ) ;
2306+ }
2307+ }
2308+ }
2309+
22202310 // ------------ Early order-dependent options ------------
22212311
22222312 // If we're building something like a dynamic library then some platforms
22232313 // need to make sure that all symbols are exported correctly from the
22242314 // dynamic library.
22252315 // Must be passed before any libraries to prevent the symbols to export from being thrown away,
22262316 // at least on some platforms (e.g. windows-gnu).
2227- cmd. export_symbols (
2228- tmpdir,
2229- crate_type,
2230- & codegen_results. crate_info . exported_symbols [ & crate_type] ,
2231- ) ;
2317+ cmd. export_symbols ( tmpdir, crate_type, & export_symbols) ;
22322318
22332319 // Can be used for adding custom CRT objects or overriding order-dependent options above.
22342320 // FIXME: In practice built-in target specs use this for arbitrary order-independent options,
@@ -2678,7 +2764,7 @@ fn add_native_libs_from_crate(
26782764 let name = lib. name . as_str ( ) ;
26792765 let verbatim = lib. verbatim ;
26802766 match lib. kind {
2681- NativeLibKind :: Static { bundle, whole_archive } => {
2767+ NativeLibKind :: Static { bundle, whole_archive, .. } => {
26822768 if link_static {
26832769 let bundle = bundle. unwrap_or ( true ) ;
26842770 let whole_archive = whole_archive == Some ( true ) ;
0 commit comments