@@ -47,7 +47,7 @@ use rustc_session::{Session, filesearch};
4747use rustc_span:: Symbol ;
4848use rustc_target:: spec:: crt_objects:: CrtObjects ;
4949use rustc_target:: spec:: {
50- BinaryFormat , Cc , CfgAbi , Env , LinkOutputKind , LinkSelfContainedComponents ,
50+ Arch , BinaryFormat , Cc , CfgAbi , Env , LinkOutputKind , LinkSelfContainedComponents ,
5151 LinkSelfContainedDefault , LinkerFeatures , LinkerFlavor , LinkerFlavorCli , Lld , Os , RelocModel ,
5252 RelroLevel , SanitizerSet , SplitDebuginfo ,
5353} ;
@@ -2413,6 +2413,69 @@ fn add_rpath_args(
24132413 }
24142414}
24152415
2416+ fn strip_numeric_suffix < ' a > ( base : & ' a str , suffix : impl AsRef < str > , fallback : & ' a str ) -> & ' a str {
2417+ if suffix. as_ref ( ) . parse :: < u32 > ( ) . is_ok ( ) { base } else { fallback }
2418+ }
2419+
2420+ fn undecorate_c_symbol < ' a > (
2421+ name : & ' a str ,
2422+ sess : & Session ,
2423+ kind : SymbolExportKind ,
2424+ ) -> Option < & ' a str > {
2425+ match sess. target . binary_format {
2426+ BinaryFormat :: MachO => {
2427+ // Mach-O: strip the leading underscore that all external symbols have.
2428+ // The Darwin linker's export_symbols will add it back.
2429+ name. strip_prefix ( '_' )
2430+ }
2431+ BinaryFormat :: Coff => {
2432+ // MSVC C++ mangled names start with '?' and use a completely different
2433+ // decorating scheme that includes '@@' as structural delimiters.
2434+ // They must not be subjected to C calling-convention undecoration.
2435+ if name. starts_with ( '?' ) {
2436+ return Some ( name) ;
2437+ }
2438+ Some ( match sess. target . arch {
2439+ Arch :: X86 => {
2440+ // COFF 32-bit: strip calling-convention decorations.
2441+ if let Some ( rest) = name. strip_prefix ( '@' ) {
2442+ // fastcall: @foo@N -> foo
2443+ rest. rsplit_once ( '@' )
2444+ . map ( |( base, suffix) | strip_numeric_suffix ( base, suffix, name) )
2445+ . unwrap_or ( name)
2446+ } else if let Some ( stripped) = name. strip_prefix ( '_' ) {
2447+ if let Some ( ( base, suffix) ) = stripped. rsplit_once ( '@' ) {
2448+ // stdcall: _foo@N -> foo
2449+ strip_numeric_suffix ( base, suffix, stripped)
2450+ } else {
2451+ // cdecl: _foo -> foo
2452+ stripped
2453+ }
2454+ } else {
2455+ // vectorcall: foo@@N -> foo
2456+ name. rsplit_once ( "@@" )
2457+ . map ( |( base, suffix) | strip_numeric_suffix ( base, suffix, name) )
2458+ . unwrap_or ( name)
2459+ }
2460+ }
2461+ Arch :: X86_64 => {
2462+ // COFF 64-bit: vectorcall mangling (foo@@N -> foo) also applies on x86_64.
2463+ name. rsplit_once ( "@@" )
2464+ . map ( |( base, suffix) | strip_numeric_suffix ( base, suffix, name) )
2465+ . unwrap_or ( name)
2466+ }
2467+ Arch :: Arm64EC if kind == SymbolExportKind :: Text => {
2468+ // Arm64EC: `#` prefix distinguishes ARM64EC text symbols from x64 thunks.
2469+ name. strip_prefix ( '#' ) . unwrap_or ( name)
2470+ }
2471+ _ => name,
2472+ } )
2473+ }
2474+ // ELF: no decoration
2475+ _ => Some ( name) ,
2476+ }
2477+ }
2478+
24162479fn add_c_staticlib_symbols (
24172480 sess : & Session ,
24182481 lib : & NativeLib ,
@@ -2454,7 +2517,14 @@ fn add_c_staticlib_symbols(
24542517 }
24552518
24562519 for symbol in object. symbols ( ) {
2457- if symbol. scope ( ) != object:: SymbolScope :: Dynamic {
2520+ // The `object` crate returns `Dynamic` for ELF/Mach-O global symbols,
2521+ // but always returns `Linkage` for COFF external symbols.
2522+ // Accept both for COFF (Windows and UEFI).
2523+ let scope = symbol. scope ( ) ;
2524+ if scope != object:: SymbolScope :: Dynamic
2525+ && !( sess. target . binary_format == BinaryFormat :: Coff
2526+ && scope == object:: SymbolScope :: Linkage )
2527+ {
24582528 continue ;
24592529 }
24602530
@@ -2469,9 +2539,10 @@ fn add_c_staticlib_symbols(
24692539 _ => continue ,
24702540 } ;
24712541
2472- // FIXME:The symbol mangle rules are slightly different in Windows(32-bit) and Apple.
2473- // Need to be resolved.
2474- out. push ( ( name. to_string ( ) , export_kind) ) ;
2542+ let Some ( undecorated) = undecorate_c_symbol ( name, sess, export_kind) else {
2543+ continue ;
2544+ } ;
2545+ out. push ( ( undecorated. to_string ( ) , export_kind) ) ;
24752546 }
24762547 }
24772548
0 commit comments