fix: x86 SMP bitcode/code-model mismatch (smp_semaphore/mutex/threads)#30
Open
fix: x86 SMP bitcode/code-model mismatch (smp_semaphore/mutex/threads)#30
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Three SMP tests on qemu_x86_64 (smp_semaphore, smp_mutex, smp_threads)
have been failing in the libgale_ffi.a build step with:
warning: linking module flags 'Code Model':
IDs have conflicting values: 'i32 2' from , and 'i32 1' from gale_ffi...
error: failed to load bitcode of module "core-...rcgu.o"
Root cause: the precompiled `core` rustlib for x86_64-unknown-none
ships bitcode tagged with code-model=kernel (=2, the target's default).
We pass -Ccode-model=small (=1) so addresses match Zephyr's lower-2GB
kernel mapping. With ffi/Cargo.toml's release profile `lto = true`
(fat LTO), rustc tries to merge the two bitcode modules and LLVM
rejects the link.
Fix: switch x86 to the release-lto profile (lto=false), which already
exists for cross-language LTO. rustc then emits a regular static
archive without doing fat LTO, so no bitcode merge is attempted. All
other release tuning (opt-level=z, codegen-units=1, panic=abort,
overflow-checks=true) is preserved via `inherits = "release"`.
Cortex-M targets are unaffected — the change is scoped inside
`if(CONFIG_X86)`. Their precompiled core ships with a matching
code-model, so fat LTO continues to work there. Reproduced the
failure locally with rustc 1.95.0 + the exact CI cargo invocation;
confirmed the fix builds clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
20fee98 to
aff4da0
Compare
The previous fix on this branch (release-lto profile) only resolved
the bitcode-merge half of the problem. CI showed it built libgale_ffi.a
clean but then failed at link with a different error:
ld.bfd: discarded output section: `.got.plt'
ld.bfd: final link failed
collect2: error: ld returned 1 exit status
Both errors root-cause to the same thing: rustup's precompiled `core`
rustlib for x86_64-unknown-none was built with the target's defaults
(code-model=kernel, PIC), which don't match the flags Zephyr's kernel
needs (code-model=small, static relocation, no PIE).
- Fat LTO (release profile) → bitcode merge rejects code-model
mismatch.
- lto=false (release-lto profile) → bitcode merge avoided, but the
precompiled core's GOT/PLT references hit the non-PIC link script
and ld.bfd refuses to discard the now-non-empty .got.plt section.
Proper fix: rebuild `core` from source with our flags via -Zbuild-std,
so the rebuilt core picks up RUSTFLAGS=-Ccode-model=small
-Crelocation-model=static and is both bitcode-compatible AND PIC-free.
Reverts to the original release profile (fat LTO works again) and
adds:
- GALE_CARGO_EXTRA_ARGS = "-Zbuild-std=core" (threaded into all 42
cargo build invocations in CMakeLists.txt)
- RUSTC_BOOTSTRAP=1 in GALE_CARGO_ENV (to permit unstable cargo
flag on stable rustc)
- rustup component add rust-src in the SMP test job
Scoped inside if(CONFIG_X86); Cortex-M codegen is byte-identical to
before.
Also addresses the underlying root-cause comment at zephyr-tests.yml
about the SMP build failures (the runtime hang remains a separate
known-issue tracked in the workflow comment).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three CI checks have been failing for at least the last several PRs:
All three fail at the same step — building `libgale_ffi.a` for `x86_64-unknown-none`:
```
error: failed to load bitcode of module
"core-fcc82a7537a7267a.core.bb170dea1013a3a3-cgu.0.rcgu.o"
error: could not compile gale-ffi (lib) due to 1 previous error
```
Root cause
Reproduced locally with rustc 1.95.0. The CI log truncates one line earlier than the actual cause; the smoking gun is a warning that precedes the error:
```
warning: linking module flags 'Code Model':
IDs have conflicting values: 'i32 2' from , and 'i32 1' from gale_ffi.5b37a6aa01c132b8-cgu.0
```
The chain:
Cortex-M doesn't trip on this because we don't override `code-model` on Cortex-M; the default matches the precompiled `core`.
Fix
Switch x86 builds from the `release` profile to the existing `release-lto` profile (which has `lto = false`), but only when the cross-language-LTO upper block hasn't already set it. `release-lto` already `inherits = "release"` so all other tuning (`opt-level="z"`, `codegen-units=1`, `panic="abort"`, `overflow-checks=true`) is preserved.
Scoped inside `if(CONFIG_X86)` so Cortex-M is byte-identical to before — the merged-in PR #27 publication-relevant LTO numbers are not at risk.
```diff
diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt
@@ -183,6 +183,29 @@ if(CONFIG_X86)
...
endif()
```
Test plan
Local repro / validation command (no Zephyr SDK needed):
```
cd gale/ffi && env RUSTFLAGS="-Crelocation-model=static -Ccode-model=small" \
GALE_MAX_SEMS=32 GALE_MAX_WAITERS=16 \
cargo build --profile release-lto --target x86_64-unknown-none \
--no-default-features \
--features sem,mutex,condvar,msgq,pipe,stack,timer,...,rbtree
```
🤖 Generated with Claude Code