@@ -266,22 +266,93 @@ fn target_has_prefixed_symbols() -> bool {
266266 target_vendor ( ) == "apple" || ( target_arch ( ) == "x86" && target_os ( ) == "windows" )
267267}
268268
269+ /// Probes whether the current `rustc` and codegen backend supports the
270+ /// `\u{1}` prefix in `#[link_name]` attributes. This prefix is an
271+ /// LLVM-specific mechanism that instructs the backend to emit the symbol
272+ /// name verbatim (without platform-specific prefixes). Backends such as
273+ /// Cranelift do not support this.
274+ ///
275+ /// Returns `true` if the `\u{1}` prefix is supported, `false` otherwise.
269276#[ cfg( not( feature = "all-bindings" ) ) ]
270- fn is_cranelift_backend ( ) -> bool {
271- // CARGO_ENCODED_RUSTFLAGS contains flags separated by 0x1f (ASCII Unit Separator)
272- if let Some ( rustflags) = optional_env ( "CARGO_ENCODED_RUSTFLAGS" ) {
273- for flag in rustflags. split ( '\x1f' ) {
274- if flag. contains ( "codegen-backend=cranelift" ) {
275- return true ;
277+ fn probe_soh_link_name_support ( ) -> bool {
278+ let probe_dir = out_dir ( ) ;
279+ let probe_src = probe_dir. join ( "probe_soh_link_name.rs" ) ;
280+ let probe_out = probe_dir. join ( "probe_soh_link_name.o" ) ;
281+
282+ if std:: fs:: write (
283+ & probe_src,
284+ r#"
285+ extern "C" { #[link_name = "\u{1}probe_soh_prefix"] fn probe(); }
286+ pub fn force_codegen() { unsafe { probe() } }
287+ "# ,
288+ )
289+ . is_err ( )
290+ {
291+ return false ;
292+ }
293+
294+ let rustc = env:: var ( "RUSTC" ) . unwrap_or_else ( |_| "rustc" . to_string ( ) ) ;
295+
296+ let mut cmd = Command :: new ( & rustc) ;
297+ cmd. arg ( & probe_src)
298+ . arg ( "--target" )
299+ . arg ( & target ( ) )
300+ . arg ( "--crate-type" )
301+ . arg ( "lib" )
302+ . arg ( "--emit=obj" )
303+ . arg ( "-o" )
304+ . arg ( & probe_out)
305+ . arg ( "--edition=2021" ) ;
306+
307+ if let Ok ( flags) = env:: var ( "CARGO_ENCODED_RUSTFLAGS" ) {
308+ for flag in flags. split ( '\x1f' ) {
309+ if !flag. is_empty ( ) {
310+ cmd. arg ( flag) ;
276311 }
277312 }
278313 }
279- false
314+
315+ let compiled = cmd. status ( ) . map ( |s| s. success ( ) ) . unwrap_or ( false ) ;
316+ if !compiled {
317+ return false ;
318+ }
319+
320+ // Read the object file and verify the SOH byte was actually stripped.
321+ // If the backend supports the \u{1} convention (LLVM), the object file
322+ // will contain the symbol "probe_soh_prefix" without a leading \x01.
323+ // If the backend does NOT support it (Cranelift), the object file will
324+ // contain "\x01probe_soh_prefix" — the SOH byte preserved literally.
325+ match std:: fs:: read ( & probe_out) {
326+ Ok ( bytes) => {
327+ let marker = b"probe_soh_prefix" ;
328+ // Search for every occurrence of the marker string in the object file.
329+ // If ANY occurrence is preceded by the SOH byte, the backend did not
330+ // strip it, so we report no support.
331+ let mut i = 0 ;
332+ let mut found = false ;
333+ while i + marker. len ( ) <= bytes. len ( ) {
334+ if & bytes[ i..i + marker. len ( ) ] == marker {
335+ found = true ;
336+ if i > 0 && bytes[ i - 1 ] == b'\x01' {
337+ // SOH byte still present — backend doesn't strip it.
338+ return false ;
339+ }
340+ i += marker. len ( ) ;
341+ } else {
342+ i += 1 ;
343+ }
344+ }
345+ // The marker string should appear at least once (as an undefined symbol
346+ // reference). If it doesn't, something unexpected happened.
347+ found
348+ }
349+ Err ( _) => false ,
350+ }
280351}
281352
282353#[ cfg( not( feature = "all-bindings" ) ) ]
283- fn target_chokes_on_u1 ( ) -> bool {
284- target_arch ( ) == "mips" || target_arch ( ) == "mips64" || is_cranelift_backend ( )
354+ fn target_chokes_on_soh ( ) -> bool {
355+ target_arch ( ) == "mips" || target_arch ( ) == "mips64" || ! probe_soh_link_name_support ( )
285356}
286357
287358#[ cfg( all( feature = "bindgen" , not( feature = "all-bindings" ) ) ) ]
@@ -509,7 +580,7 @@ static mut AWS_LC_SYS_CMAKE_BUILDER: Option<bool> = None;
509580static mut AWS_LC_SYS_NO_PREGENERATED_SRC : bool = false ;
510581static mut AWS_LC_SYS_EFFECTIVE_TARGET : String = String :: new ( ) ;
511582static mut AWS_LC_SYS_NO_JITTER_ENTROPY : Option < bool > = None ;
512- static mut AWS_LC_SYS_NO_U1_BINDINGS : Option < bool > = None ;
583+ static mut AWS_LC_SYS_NO_SOH_BINDINGS : Option < bool > = None ;
513584
514585static mut AWS_LC_SYS_C_STD : CStdRequested = CStdRequested :: None ;
515586
@@ -528,7 +599,7 @@ fn initialize() {
528599 AWS_LC_SYS_EFFECTIVE_TARGET =
529600 optional_env_crate_target ( "EFFECTIVE_TARGET" ) . unwrap_or_default ( ) ;
530601 AWS_LC_SYS_NO_JITTER_ENTROPY = env_crate_var_to_bool ( "NO_JITTER_ENTROPY" ) ;
531- AWS_LC_SYS_NO_U1_BINDINGS = env_crate_var_to_bool ( "NO_U1_BINDINGS " ) ;
602+ AWS_LC_SYS_NO_SOH_BINDINGS = env_crate_var_to_bool ( "NO_SOH_BINDINGS " ) ;
532603 }
533604
534605 if !is_external_bindgen_requested ( ) . unwrap_or ( false )
@@ -537,7 +608,7 @@ fn initialize() {
537608 #[ cfg( feature = "all-bindings" ) ]
538609 {
539610 assert ! (
540- use_no_u1_bindings ( ) != Some ( true ) ,
611+ use_no_soh_bindings ( ) != Some ( true ) ,
541612 "Bindgen currently cannot generate prefixed bindings w/o the \\ x01 prefix." ,
542613 ) ;
543614 let target = effective_target ( ) ;
@@ -566,18 +637,18 @@ fn initialize() {
566637 }
567638 #[ cfg( not( feature = "all-bindings" ) ) ]
568639 {
569- if use_no_u1_bindings ( ) == Some ( true )
570- || ( target_chokes_on_u1 ( ) && use_no_u1_bindings ( ) . is_none ( ) )
640+ if use_no_soh_bindings ( ) == Some ( true )
641+ || ( target_chokes_on_soh ( ) && use_no_soh_bindings ( ) . is_none ( ) )
571642 {
572- if is_cranelift_backend ( ) {
643+ if ! probe_soh_link_name_support ( ) {
573644 emit_warning (
574- "Cranelift codegen backend detected . Using universal_no_u1 bindings." ,
645+ "Codegen backend does not support the \\ u{1} link_name prefix . Using universal_no_soh bindings." ,
575646 ) ;
576647 }
577648 if target_has_prefixed_symbols ( ) {
578- emit_rustc_cfg ( "universal-no-u1 -prefixed" ) ;
649+ emit_rustc_cfg ( "universal-no-soh -prefixed" ) ;
579650 } else {
580- emit_rustc_cfg ( "universal-no-u1 " ) ;
651+ emit_rustc_cfg ( "universal-no-soh " ) ;
581652 }
582653 } else if target_has_prefixed_symbols ( ) {
583654 emit_rustc_cfg ( "universal-prefixed" ) ;
@@ -638,8 +709,8 @@ fn disable_jitter_entropy() -> Option<bool> {
638709 unsafe { AWS_LC_SYS_NO_JITTER_ENTROPY }
639710}
640711
641- fn use_no_u1_bindings ( ) -> Option < bool > {
642- unsafe { AWS_LC_SYS_NO_U1_BINDINGS }
712+ fn use_no_soh_bindings ( ) -> Option < bool > {
713+ unsafe { AWS_LC_SYS_NO_SOH_BINDINGS }
643714}
644715
645716fn get_crate_cc ( ) -> Option < String > {
@@ -711,8 +782,8 @@ fn prepare_cargo_cfg() {
711782 println ! ( "cargo:rustc-check-cfg=cfg(x86_64_unknown_linux_gnu)" ) ;
712783 println ! ( "cargo:rustc-check-cfg=cfg(x86_64_unknown_linux_musl)" ) ;
713784 println ! ( "cargo:rustc-check-cfg=cfg(universal)" ) ;
714- println ! ( "cargo:rustc-check-cfg=cfg(universal_no_u1 )" ) ;
715- println ! ( "cargo:rustc-check-cfg=cfg(universal_no_u1_prefixed )" ) ;
785+ println ! ( "cargo:rustc-check-cfg=cfg(universal_no_soh )" ) ;
786+ println ! ( "cargo:rustc-check-cfg=cfg(universal_no_soh_prefixed )" ) ;
716787 println ! ( "cargo:rustc-check-cfg=cfg(universal_prefixed)" ) ;
717788 }
718789}
0 commit comments