-
-
Notifications
You must be signed in to change notification settings - Fork 28
Description
Hi, I've observed occasional panics in code running on arm64 CPUs with support for SIMD instructions. I believe the issue is the same as the one described in this blog post in which the function doesn't save the frame pointer properly:
The first
stpinstruction is key here. It decrements the stack pointer by 16, then saves the current values ofx29andx30on the stack starting at the newly decremented stack pointer. Thex29register is the frame pointer register for ARM64. So, it looks like this function saves the frame pointer as it should, right?Turns out it's wrong in a non-obvious way. The Go compiler saves the caller's frame pointer one word below the function's stack frame. See "the one-instruction window" for some diagrams that illustrate how the frame is laid out. So, the top word of a function's stack frame on entry actually belongs to the caller. That
stpinstruction is actually savingx30(the link register) where the caller saved the frame pointer. When the function returns, it will restore its caller's frame pointer to the frame pointer register, and that frame pointer now points to an invalid frame pointer (an instruction address fromx30). That invalid frame pointer will be there until the caller returns.
The author of the blog post also linked to the PR to fix the issue and I think the same change would work here as well. The only additional wrinkle is that the branch instructions would need to be updated as well as currently the offsets are fixed because they use WORD instructions, but the offsets would need to change with the added instructions for the fix.
I'd be happy to open a PR with these changes, just wanted to open an issue first to provide context.