Skip to content

Commit 4bfd612

Browse files
committed
Probe for SOH symbols
1 parent 198d9ba commit 4bfd612

7 files changed

Lines changed: 123 additions & 37 deletions

File tree

.github/workflows/sys-bindings-generator.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -278,16 +278,16 @@ jobs:
278278
AWS_LC_SYS_PREGENERATING_BINDINGS: "1"
279279
run: |
280280
cargo test -p aws-lc-sys --no-default-features --features bindgen
281-
- name: Create bindings with the \u{1} stripped
281+
- name: Create SOH-stripped bindings
282282
if: matrix.os == 'ubuntu-latest'
283283
working-directory: aws-lc-sys/src
284284
run: |
285-
sed 's/#\[link_name = "\\u{1}aws_lc_/#[link_name = "aws_lc_/g' universal_crypto.rs > universal_no_u1_crypto.rs
286-
- name: Create prefixed bindings with the \u{1} stripped
285+
sed 's/#\[link_name = "\\u{1}aws_lc_/#[link_name = "aws_lc_/g' universal_crypto.rs > universal_no_soh_crypto.rs
286+
- name: Create SOH-stripped prefixed bindings
287287
if: matrix.os == 'macos-latest'
288288
working-directory: aws-lc-sys/src
289289
run: |
290-
sed 's/#\[link_name = "\\u{1}_aws_lc_/#[link_name = "aws_lc_/g' universal_prefixed_crypto.rs > universal_no_u1_prefixed_crypto.rs
290+
sed 's/#\[link_name = "\\u{1}_aws_lc_/#[link_name = "aws_lc_/g' universal_prefixed_crypto.rs > universal_no_soh_prefixed_crypto.rs
291291
- name: Commit & Push changes
292292
run: ./scripts/ci/ci_add_commit_rebase_push.sh "Generated bindings from ${{ matrix.os }}"
293293
collect-src-and-commit:

.github/workflows/tests.yml

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -702,12 +702,12 @@ jobs:
702702
- name: Run tests
703703
run: cargo test -p aws-lc-rs --all-targets
704704

705-
build-env-no-u1-bindings-test:
705+
build-env-no-soh-bindings-test:
706706
if: github.repository_owner == 'aws'
707-
name: aws-lc-rs build-env-no-u1-bindings-test
707+
name: aws-lc-rs build-env-no-soh-bindings-test
708708
runs-on: ${{ matrix.os }}
709709
env:
710-
AWS_LC_SYS_NO_U1_BINDINGS: 1
710+
AWS_LC_SYS_NO_SOH_BINDINGS: 1
711711
strategy:
712712
fail-fast: false
713713
matrix:
@@ -731,10 +731,6 @@ jobs:
731731
if: github.repository_owner == 'aws'
732732
name: aws-lc-rs cranelift-backend-test (${{ matrix.target }})
733733
runs-on: ${{ matrix.os }}
734-
env:
735-
# Cranelift requires panic=abort as it doesn't fully support unwinding.
736-
# -Zpanic_abort_tests is required to run tests with panic=abort.
737-
RUSTFLAGS: -Zcodegen-backend=cranelift -Cpanic=abort -Zpanic_abort_tests
738734
strategy:
739735
fail-fast: false
740736
matrix:
@@ -756,6 +752,25 @@ jobs:
756752
components: rustc-codegen-cranelift-preview
757753
- name: Set Rust toolchain override
758754
run: rustup override set ${{ steps.toolchain.outputs.name }}
755+
- name: Configure Cranelift via .cargo/config.toml
756+
shell: bash
757+
run: |
758+
mkdir -p .cargo
759+
cat > .cargo/config.toml << 'EOF'
760+
[unstable]
761+
codegen-backend = true
762+
763+
[profile.dev]
764+
codegen-backend = "cranelift"
765+
panic = "abort"
766+
767+
[profile.test]
768+
codegen-backend = "cranelift"
769+
panic = "abort"
770+
771+
[build]
772+
rustflags = ["-Zpanic_abort_tests"]
773+
EOF
759774
- name: Remove other universal bindings
760775
shell: bash
761776
run: |

aws-lc-sys/builder/main.rs

Lines changed: 93 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -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;
509580
static mut AWS_LC_SYS_NO_PREGENERATED_SRC: bool = false;
510581
static mut AWS_LC_SYS_EFFECTIVE_TARGET: String = String::new();
511582
static 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

514585
static 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

645716
fn 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
}

aws-lc-sys/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ macro_rules! platform_binding {
2020
}
2121

2222
platform_binding!(universal_prefixed, universal_prefixed_crypto);
23-
platform_binding!(universal_no_u1_prefixed, universal_no_u1_prefixed_crypto);
24-
platform_binding!(universal_no_u1, universal_no_u1_crypto);
23+
platform_binding!(universal_no_soh_prefixed, universal_no_soh_prefixed_crypto);
24+
platform_binding!(universal_no_soh, universal_no_soh_crypto);
2525
platform_binding!(universal, universal_crypto);
2626

2727
platform_binding!(aarch64_linux_android, aarch64_linux_android_crypto);
File renamed without changes.

book/src/resources.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ The target-specific variant takes precedence when both are set.
6767
it contains. This may be useful in certain linking scenarios but can cause symbol conflicts
6868
if multiple versions are linked.
6969

70-
* **`AWS_LC_SYS_NO_U1_BINDINGS`**
70+
* **`AWS_LC_SYS_NO_SOH_BINDINGS`**
7171

72-
When set to `1`, uses bindings that don't include the `\x01` prefix on symbol names.
72+
When set to `1`, uses bindings that don't include the `\x01` (SOH) prefix on symbol names.
7373
This is automatically enabled for certain backends (like Cranelift) and architectures
7474
(like MIPS) that don't support the prefixed symbols.
7575

0 commit comments

Comments
 (0)