1+ use std:: borrow:: Cow ;
12use std:: env;
23use std:: error:: Error ;
34use std:: ffi:: OsString ;
@@ -22,7 +23,7 @@ use tracing::trace;
2223
2324use super :: metadata:: { create_compressed_metadata_file, search_for_section} ;
2425use super :: rmeta_link;
25- use super :: symbol_edit:: apply_hide ;
26+ use super :: symbol_edit:: { apply_edits , collect_internal_names } ;
2627use crate :: common;
2728// Public for ArchiveBuilderBuilder::extract_bundled_libs
2829pub use crate :: errors:: ExtractBundledLibsError ;
@@ -314,12 +315,18 @@ pub enum AddArchiveKind<'a> {
314315 Other ,
315316}
316317
318+ pub struct ArchiveSymbols {
319+ pub exported : FxHashSet < String > ,
320+ pub rename_suffix : Option < String > ,
321+ pub hide : bool ,
322+ }
323+
317324pub trait ArchiveBuilder {
318325 fn add_file ( & mut self , path : & Path , kind : ArchiveEntryKind ) ;
319326
320327 fn add_archive ( & mut self , archive : & Path , kind : AddArchiveKind < ' _ > ) -> io:: Result < ( ) > ;
321328
322- fn build ( self : Box < Self > , output : & Path , exported_symbols : Option < FxHashSet < String > > ) -> bool ;
329+ fn build ( self : Box < Self > , output : & Path , symbols : Option < ArchiveSymbols > ) -> bool ;
323330}
324331
325332fn target_archive_format_to_object_kind ( format : & str ) -> Option < ObjectArchiveKind > {
@@ -534,9 +541,9 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> {
534541
535542 /// Combine the provided files, rlibs, and native libraries into a single
536543 /// `Archive`.
537- fn build ( self : Box < Self > , output : & Path , exported_symbols : Option < FxHashSet < String > > ) -> bool {
544+ fn build ( self : Box < Self > , output : & Path , symbols : Option < ArchiveSymbols > ) -> bool {
538545 let sess = self . sess ;
539- match self . build_inner ( output, exported_symbols ) {
546+ match self . build_inner ( output, symbols ) {
540547 Ok ( any_members) => any_members,
541548 Err ( error) => {
542549 sess. dcx ( ) . emit_fatal ( ArchiveBuildFailure { path : output. to_owned ( ) , error } )
@@ -546,11 +553,7 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> {
546553}
547554
548555impl < ' a > ArArchiveBuilder < ' a > {
549- fn build_inner (
550- self ,
551- output : & Path ,
552- exported_symbols : Option < FxHashSet < String > > ,
553- ) -> io:: Result < bool > {
556+ fn build_inner ( self , output : & Path , symbols : Option < ArchiveSymbols > ) -> io:: Result < bool > {
554557 let archive_kind = match & * self . sess . target . archive_format {
555558 "gnu" => ArchiveKind :: Gnu ,
556559 "bsd" => ArchiveKind :: Bsd ,
@@ -562,6 +565,39 @@ impl<'a> ArArchiveBuilder<'a> {
562565 }
563566 } ;
564567
568+ // Collect all internally-defined symbol names across every Rust object file.
569+ // This set is needed because rename must also apply to *undefined* references
570+ // (cross-object calls within the staticlib), but we cannot use `!exported.contains(name)`
571+ // alone — that would also match external C symbols like `malloc` which must not be renamed.
572+ let rename = if let Some ( sym) = & symbols
573+ && let Some ( rename_suffix) = sym. rename_suffix . as_deref ( )
574+ {
575+ let mut names = FxHashSet :: default ( ) ;
576+ for ( _, entry) in & self . entries {
577+ if entry. kind != ArchiveEntryKind :: RustObj {
578+ continue ;
579+ }
580+ match & entry. source {
581+ ArchiveEntrySource :: Archive { archive_index, file_range } => {
582+ let src_archive = & self . src_archives [ * archive_index] ;
583+ let start = file_range. 0 as usize ;
584+ let end = start + file_range. 1 as usize ;
585+ if let Some ( data) = src_archive. 1 . get ( start..end) {
586+ collect_internal_names ( data, & sym. exported , & mut names) ;
587+ }
588+ }
589+ ArchiveEntrySource :: File ( file) => {
590+ if let Ok ( data) = fs:: read ( file) {
591+ collect_internal_names ( & data, & sym. exported , & mut names) ;
592+ }
593+ }
594+ }
595+ }
596+ Some ( ( names, rename_suffix) )
597+ } else {
598+ None
599+ } ;
600+
565601 let mut entries = Vec :: new ( ) ;
566602
567603 for ( entry_name, entry) in self . entries {
@@ -588,9 +624,9 @@ impl<'a> ArArchiveBuilder<'a> {
588624 } ;
589625
590626 if entry. kind == ArchiveEntryKind :: RustObj
591- && let Some ( exported ) = & exported_symbols
627+ && let Some ( sym ) = & symbols
592628 {
593- Box :: new ( apply_hide ( data, exported) )
629+ Box :: new ( apply_edits ( data, & sym . exported , sym . hide , rename . as_ref ( ) ) )
594630 } else {
595631 Box :: new ( data)
596632 }
@@ -602,9 +638,13 @@ impl<'a> ArArchiveBuilder<'a> {
602638 )
603639 . map_err ( |err| io_error_context ( "failed to map object file" , err) ) ?;
604640 if entry. kind == ArchiveEntryKind :: RustObj
605- && let Some ( exported ) = & exported_symbols
641+ && let Some ( sym ) = & symbols
606642 {
607- Box :: new ( apply_hide ( & mmap, exported) )
643+ let edited = apply_edits ( & mmap, & sym. exported , sym. hide , rename. as_ref ( ) ) ;
644+ match edited {
645+ Cow :: Borrowed ( _) => Box :: new ( mmap) as Box < dyn AsRef < [ u8 ] > > ,
646+ Cow :: Owned ( v) => Box :: new ( v) ,
647+ }
608648 } else {
609649 Box :: new ( mmap) as Box < dyn AsRef < [ u8 ] > >
610650 }
0 commit comments