Repository navigation
fix(arm64): use x17 instead of x10 to avoid clobbering the 11th argument slot - #189
Merged
agiledragon merged 3 commits intoSep 9, 2026
Merged
Conversation
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.
fix(arm64): avoid clobbering R10 (11th argument slot) in the stub trampoline
What
Fix a SIGBUS on arm64 (darwin/arm64 & linux/arm64) caused by the stub trampoline clobbering register R10, which holds the 11th argument slot.
Why
In
jmp_arm64.go,buildJmpDirectiveuses x10 as a temporary register:In Go's arm64 ABI, R0–R15 are the integer argument/result registers, so R10 is the 11th argument slot. Moreover, struct arguments are flattened field-by-field, so a signature like
func Parse(in SomeBigStruct, out any)can easily putout's data word in R10.When the target function is stubbed,
LDR x10, [x26]overwrites the caller's 11th argument slot with the mock's own code address. If the mock dereferences or writes through that argument (e.g.*out.(*T) = ...), it writes into the mock's read-only text segment — SIGBUS on darwin/arm64 (W^X), SIGSEGV on linux/arm64.Fix
Use x17 (the platform-reserved temp register
REGRT2, never used to pass arguments) instead of x10:MOVZ/MOVK x26is unchanged (x26 is callee-saved and not on the argument path).Test
Added
TestApplyFuncArm64R10: stubs a function whose signature puts ananyargument's data word in R10, and the mock writes through it. On unpatched arm64 this writes to the mock's own text segment (SIGBUS); with the fix it passes.Scope
jmp_arm64.go).jmp_*.gowith non-argument temp registers — unaffected.Related: #181