@@ -11,7 +11,7 @@ use std::{env, fmt, fs, io, mem, str};
1111
1212use cc:: windows_registry;
1313use itertools:: Itertools ;
14- use object:: { Object , ObjectSection } ;
14+ use object:: { Object , ObjectSection , ObjectSymbol } ;
1515use regex:: Regex ;
1616use rustc_arena:: TypedArena ;
1717use rustc_ast:: CRATE_NODE_ID ;
@@ -2172,42 +2172,80 @@ fn add_rpath_args(
21722172 }
21732173}
21742174
2175- fn add_c_staticlib_symbols ( sess : & Session , name : & str , out : & mut Vec < ( String , SymbolExportKind ) > ) {
2175+ fn add_c_staticlib_symbols (
2176+ sess : & Session ,
2177+ name : & str ,
2178+ out : & mut Vec < ( String , SymbolExportKind ) > ,
2179+ ) -> io:: Result < ( ) > {
21762180 for search_path in sess. target_filesearch ( ) . search_paths ( PathKind :: Native ) {
21772181 let file_path = search_path. dir . join ( name) ;
2178- if file_path. exists ( ) {
2179- let archive_data = unsafe {
2180- Mmap :: map ( File :: open ( file_path) . expect ( "couldn't open c staticlib" ) )
2181- . expect ( "couldn't map c staticlib" )
2182- } ;
2183- let archive = object:: read:: archive:: ArchiveFile :: parse ( & * archive_data)
2184- . expect ( "wanted an c staticlib" ) ;
2185- for member in archive. members ( ) {
2186- let member = member. unwrap ( ) ;
2187- let data = member. data ( & * archive_data) . unwrap ( ) ;
2188-
2189- // clang LTO: raw LLVM bitcode
2190- if data. len ( ) >= 4 && & data[ 0 ..4 ] == b"BC\xc0 \xde " {
2191- return ;
2192- }
2182+ if !file_path. exists ( ) {
2183+ continue ;
2184+ }
21932185
2194- // gcc / clang ELF LTO
2195- let object = object:: File :: parse ( & * data) . unwrap ( ) ;
2196- if object. sections ( ) . into_iter ( ) . any ( |s| {
2197- s. name ( ) . unwrap ( ) . starts_with ( ".gnu.lto_" ) || s. name ( ) . unwrap ( ) == ".llvm.lto"
2198- } ) {
2199- return ;
2200- }
2186+ let archive_map = unsafe { Mmap :: map ( File :: open ( & file_path) ?) ? } ;
2187+
2188+ let archive = object:: read:: archive:: ArchiveFile :: parse ( & * archive_map)
2189+ . map_err ( |e| io:: Error :: new ( io:: ErrorKind :: InvalidData , e) ) ?;
2190+
2191+ for member in archive. members ( ) {
2192+ let member = member. map_err ( |e| io:: Error :: new ( io:: ErrorKind :: InvalidData , e) ) ?;
2193+
2194+ let data = member
2195+ . data ( & * archive_map)
2196+ . map_err ( |e| io:: Error :: new ( io:: ErrorKind :: InvalidData , e) ) ?;
2197+
2198+ // clang LTO: raw LLVM bitcode
2199+ if data. starts_with ( b"BC\xc0 \xde " ) {
2200+ return Err ( io:: Error :: new (
2201+ io:: ErrorKind :: InvalidData ,
2202+ "LLVM bitcode object in C static library (LTO not supported)" ,
2203+ ) ) ;
22012204 }
2202- for symbol in archive. symbols ( ) . unwrap ( ) . unwrap ( ) {
2203- let symbol = symbol. unwrap ( ) ;
2204- out. push ( (
2205- String :: from_utf8 ( symbol. name ( ) . to_vec ( ) ) . unwrap ( ) ,
2206- SymbolExportKind :: Text ,
2205+
2206+ let object = object:: File :: parse ( & * data)
2207+ . map_err ( |e| io:: Error :: new ( io:: ErrorKind :: InvalidData , e) ) ?;
2208+
2209+ // gcc / clang ELF / Mach-O LTO
2210+ if object. sections ( ) . any ( |s| {
2211+ s. name ( ) . map ( |n| n. starts_with ( ".gnu.lto_" ) || n == ".llvm.lto" ) . unwrap_or ( false )
2212+ } ) {
2213+ return Err ( io:: Error :: new (
2214+ io:: ErrorKind :: InvalidData ,
2215+ "LTO object in C static library is not supported" ,
22072216 ) ) ;
22082217 }
2218+
2219+ for symbol in object. symbols ( ) {
2220+ if symbol. scope ( ) != object:: SymbolScope :: Dynamic {
2221+ continue ;
2222+ }
2223+
2224+ let mut name = match symbol. name ( ) {
2225+ Ok ( n) => n,
2226+ Err ( _) => continue ,
2227+ } ;
2228+
2229+ if sess. target . is_like_darwin {
2230+ if let Some ( stripped) = name. strip_prefix ( '_' ) {
2231+ name = stripped;
2232+ }
2233+ }
2234+
2235+ let export_kind = match symbol. kind ( ) {
2236+ object:: SymbolKind :: Text => SymbolExportKind :: Text ,
2237+ object:: SymbolKind :: Data => SymbolExportKind :: Data ,
2238+ _ => continue ,
2239+ } ;
2240+
2241+ out. push ( ( name. to_string ( ) , export_kind) ) ;
2242+ }
22092243 }
2244+
2245+ return Ok ( ( ) ) ;
22102246 }
2247+
2248+ Ok ( ( ) )
22112249}
22122250
22132251/// Produce the linker command line containing linker path and arguments.
@@ -2241,9 +2279,13 @@ fn linker_with_args(
22412279 let link_output_kind = link_output_kind ( sess, crate_type) ;
22422280
22432281 let mut export_symbols = codegen_results. crate_info . exported_symbols [ & crate_type] . clone ( ) ;
2244- if !sess. opts . unstable_opts . include_libs . is_empty ( ) {
2245- for name in & sess. opts . unstable_opts . include_libs {
2246- add_c_staticlib_symbols ( & sess, name, & mut export_symbols) ;
2282+ if crate_type == CrateType :: Cdylib
2283+ && !sess. opts . unstable_opts . export_c_static_library_symbols . is_empty ( )
2284+ {
2285+ for name in & sess. opts . unstable_opts . export_c_static_library_symbols {
2286+ if let Err ( err) = add_c_staticlib_symbols ( & sess, name, & mut export_symbols) {
2287+ sess. dcx ( ) . fatal ( format ! ( "failed to process C static library `{}`: {}" , name, err) ) ;
2288+ }
22472289 }
22482290 }
22492291
0 commit comments