@@ -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} ;
@@ -2290,6 +2290,57 @@ fn add_rpath_args(
22902290 }
22912291}
22922292
2293+ fn undecorate_c_symbol ( name : & str , sess : & Session , kind : SymbolExportKind ) -> String {
2294+ if sess. target . is_like_darwin {
2295+ // Mach-O: strip the leading underscore that all C symbols have.
2296+ // The Darwin linker's export_symbols will add it back.
2297+ name. strip_prefix ( '_' ) . map ( |s| s. to_string ( ) ) . unwrap_or ( name. to_string ( ) )
2298+ } else if sess. target . is_like_windows {
2299+ match sess. target . arch {
2300+ Arch :: X86 => {
2301+ // COFF 32-bit: strip calling-convention decorations.
2302+ if let Some ( rest) = name. strip_prefix ( '@' ) {
2303+ // fastcall: @foo@N -> foo
2304+ rest. split_once ( '@' )
2305+ . map ( |( base, _) | base. to_string ( ) )
2306+ . unwrap_or ( name. to_string ( ) )
2307+ } else if let Some ( stripped) = name. strip_prefix ( '_' ) {
2308+ if let Some ( ( base, suffix) ) = stripped. split_once ( '@' ) {
2309+ // stdcall: _foo@N -> foo
2310+ if suffix. parse :: < u32 > ( ) . is_ok ( ) {
2311+ base. to_string ( )
2312+ } else {
2313+ stripped. to_string ( )
2314+ }
2315+ } else {
2316+ // cdecl: _foo -> foo
2317+ stripped. to_string ( )
2318+ }
2319+ } else {
2320+ // vectorcall: foo@@N -> foo
2321+ name. split_once ( "@@" )
2322+ . map ( |( base, suffix) | {
2323+ if suffix. parse :: < u32 > ( ) . is_ok ( ) {
2324+ base. to_string ( )
2325+ } else {
2326+ name. to_string ( )
2327+ }
2328+ } )
2329+ . unwrap_or ( name. to_string ( ) )
2330+ }
2331+ }
2332+ Arch :: Arm64EC if kind == SymbolExportKind :: Text => {
2333+ // Arm64EC: only text symbols have '#' prefix decoration
2334+ name. strip_prefix ( '#' ) . map ( |s| s. to_string ( ) ) . unwrap_or ( name. to_string ( ) )
2335+ }
2336+ _ => name. to_string ( ) ,
2337+ }
2338+ } else {
2339+ // ELF, COFF x86_64: no decoration
2340+ name. to_string ( )
2341+ }
2342+ }
2343+
22932344fn add_c_staticlib_symbols (
22942345 sess : & Session ,
22952346 lib : & NativeLib ,
@@ -2331,7 +2382,13 @@ fn add_c_staticlib_symbols(
23312382 }
23322383
23332384 for symbol in object. symbols ( ) {
2334- if symbol. scope ( ) != object:: SymbolScope :: Dynamic {
2385+ // The `object` crate returns `Dynamic` for ELF/Mach-O global symbols,
2386+ // but always returns `Linkage` for COFF external symbols.
2387+ // Accept both on Windows.
2388+ let scope = symbol. scope ( ) ;
2389+ if scope != object:: SymbolScope :: Dynamic
2390+ && !( sess. target . is_like_windows && scope == object:: SymbolScope :: Linkage )
2391+ {
23352392 continue ;
23362393 }
23372394
@@ -2346,9 +2403,8 @@ fn add_c_staticlib_symbols(
23462403 _ => continue ,
23472404 } ;
23482405
2349- // FIXME:The symbol mangle rules are slightly different in Windows(32-bit) and Apple.
2350- // Need to be resolved.
2351- out. push ( ( name. to_string ( ) , export_kind) ) ;
2406+ let undecorated = undecorate_c_symbol ( name, sess, export_kind) ;
2407+ out. push ( ( undecorated, export_kind) ) ;
23522408 }
23532409 }
23542410
0 commit comments