Repository navigation
all: align the stack for C calls on linux/386 - #558
Merged
hajimehoshi merged 1 commit intoNov 1, 2026
Merged
Conversation
hajimehoshi
requested review from
TotallyGamerJet
and
a balanced review from Copilot
November 1, 2026 10:34
Member
Author
|
@TotallyGamerJet PTAL |
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
The Linux/386 C-call stack-alignment fix has no active review issues.
No open issues 🎉
What changed in this PR
Fixes Linux/386 C-call stack alignment in PureGo’s trampolines, addressing the ABI violation behind the crashes reported in #458.
Changes:
- Aligns the stack to 16 bytes before C calls in
syscallXand fakecgo’scall5, preserving the original stack pointer for restoration. - Adds a regression test for call-site stack alignment on Linux/386 and amd64.
- Renames 386 assembly operands to match their Go declarations and resolve
go vetreports.
| File | Description |
|---|---|
testdata/abitest/abi_test.c |
Adds a C helper that measures call-site stack alignment. |
sys_386.s |
Aligns the C-call stack and restores the saved stack pointer. |
internal/fakecgo/trampolines_386.s |
Aligns call5’s stack and corrects assembly operand names. |
func_test.go |
Adds the stack-alignment regression test. |
Review effort: Balanced
The i386 System V ABI requires the stack pointer to be 16-byte aligned at a call, and compilers rely on it for aligned SSE stack accesses such as movaps, which fault otherwise. Two linux/386 trampolines broke this. syscallX is entered on an aligned stack from runtime.asmcgocall, but its register saves and fixed frame left ESP at 12 mod 16 at the call. linux/386 uses this path with Cgo enabled too. call5 in fakecgo, which calls pthread_create, malloc, setenv and others, did not realign at all, so its alignment depended on the calling Go frame. Save SP in the callee-saved BP and align SP with ANDL before placing the arguments in both trampolines, as call5 already does on amd64. Add a test that calls a naked C function returning the caller's stack pointer modulo 16 at the call. It runs on linux/386 and on amd64, where the alignment in syscallX depends on its frame size. Also rename the FP operands in the 386 setg_trampoline and call5 to match their Go declarations, which fixes go vet's asmdecl reports. The generated code is unchanged. Closes ebitengine#458 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hajimehoshi
force-pushed
the
claude/linux-386-stack-align
branch
from
November 1, 2026 13:02
16f7f60 to
852ac27
Compare
hajimehoshi
added a commit
that referenced
this pull request
Nov 1, 2026
The i386 System V ABI requires the stack pointer to be 16-byte aligned at a call, and compilers rely on it for aligned SSE stack accesses such as movaps, which fault otherwise. Two linux/386 trampolines broke this. syscallX is entered on an aligned stack from runtime.asmcgocall, but its register saves and fixed frame left ESP at 12 mod 16 at the call. linux/386 uses this path with Cgo enabled too. call5 in fakecgo, which calls pthread_create, malloc, setenv and others, did not realign at all, so its alignment depended on the calling Go frame. Save SP in the callee-saved BP and align SP with ANDL before placing the arguments in both trampolines, as call5 already does on amd64. Add a test that calls a naked C function returning the caller's stack pointer modulo 16 at the call. It runs on linux/386 and on amd64, where the alignment in syscallX depends on its frame size. Also rename the FP operands in the 386 setg_trampoline and call5 to match their Go declarations, which fixes go vet's asmdecl reports. The generated code is unchanged. Closes #458 Co-authored-by: Claude Opus 5.5 <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.
What issue is this addressing?
Closes #458
What type of issue is this addressing?
bug
What this PR does | solves
The i386 System V ABI requires the stack pointer to be 16-byte aligned at a call, and compilers rely on it for aligned SSE stack accesses such as
movaps, which fault withsigcode=128 addr=0x0otherwise. Two linux/386 trampolines broke this:syscallX(sys_386.s) is entered on an aligned stack fromruntime.asmcgocall, but its fourPUSHLs andSUBL $160left ESP at 12 mod 16 atCALL AX. linux/386 uses this path with Cgo enabled too, sincesyscall_cgo_linux.goexcludes 386.call5(internal/fakecgo/trampolines_386.s), used forpthread_create,malloc,setenvand others, did not realign at all, so its alignment depended on the calling Go frame.Besides the musl/libstdc++ crash in the issue, this crashes Ebitengine's
GOARCH=386CI on Ubuntu 26.04 (Mesa 26.0.8) inglXQueryExtensionsString.Both trampolines now save SP in the callee-saved BP and align SP with
ANDL $~15, SPbefore placing the arguments, ascall5intrampolines_amd64.salready does.TestRegisterFunc_StackAlignmentcalls a naked C function that returns the caller's stack pointer modulo 16 at the call. It runs on linux/386 and on amd64, where the alignment insyscallXdepends on its frame size.The 386
setg_trampolineandcall5FP operands are also renamed to match their Go declarations (G,ret), which fixesGOARCH=386 go vet's asmdecl reports. The generated code is byte-identical.Verification:
syscallX's frame is shifted by 8 bytes.internal/graphicscommand386 tests crash with the CI signature before the fix and pass after.Filed by Claude (Claude Code), on behalf of @hajimehoshi
🤖 Generated with Claude Code