Skip to content

proc: fix arm64 crosscall2 SP restore for cgo stacktraces - #4399

Open
derekparker wants to merge 4 commits into
go-delve:masterfrom
derekparker:fix/cgo-stacktrace-arm64
Open

proc: fix arm64 crosscall2 SP restore for cgo stacktraces#4399
derekparker wants to merge 4 commits into
go-delve:masterfrom
derekparker:fix/cgo-stacktrace-arm64

Conversation

@derekparker

@derekparker derekparker commented Jul 21, 2026

Copy link
Copy Markdown
Member

crosscall2 adjusts SP (e.g. SUB $(8*24), RSP on arm64) but never spills it. Delve was either restoring SP from the saved frame pointer (linux/arm64) or loading *(SP+N) (other LR arches). Both are wrong: the FP fallback only works when C keeps a frame pointer, and *(SP+N) is the caller's stack contents.

After the TeamCity Ubuntu 20.04 -> 24.04 bump (newer GCC), cgo-compiled C more often omits frame pointers, so TestCgoStacktrace failed on linux/arm64 at the C→Go callback step.

Restore the caller SP as SP + framesize, matching what each arch's crosscall2 epilogue adds back. Applied on arm64, riscv64, loong64, and ppc64le (with corrected ppc64le BP/LR save slots). Re-enable TestCgoStacktrace on linux/ppc64le.

darwin/arm64 shares the arm64 path and gets the same correct restore.

@derekparker
derekparker force-pushed the fix/cgo-stacktrace-arm64 branch from bf00847 to c79d5c1 Compare July 22, 2026 16:49
crosscall2 does SUB $(8*24), RSP but never spills SP. Linux/arm64 was
restoring SP from the saved frame pointer, which only works when C
frames keep a frame pointer; with newer GCC (Ubuntu 24.04 CI) that omits
them, TestCgoStacktrace skips C frames after a cgo callback. Loading
*(SP+8*24) is also wrong (that slot is the caller's stack contents).
Restore the caller SP as SP+8*24, matching what crosscall2's epilogue
adds back.
@derekparker
derekparker force-pushed the fix/cgo-stacktrace-arm64 branch from fe786cb to 1071039 Compare July 23, 2026 17:34
Apply the same SP+framesize restore used on arm64: crosscall2 adjusts SP
but does not spill it, so loading from SP+N reads caller stack contents.
Also correct ppc64le BP/LR slot offsets from the host ABI save macros, and
re-enable TestCgoStacktrace on linux/ppc64le.
The arm64 crosscall2 SP restore fix applies to all GOOS via arm64_arch.go,
so re-enable the previously skipped windows/arm64 cgo stacktrace test.
C frames on windows/arm64 use PE .pdata/.xdata from clang, not DWARF
.debug_frame. Delve does not unwind via .pdata yet, so step 1 fails
inside C before asmcgocall or crosscall2. That is unrelated to the
arm64 crosscall2 SP restore this PR fixes.
@derekparker
derekparker marked this pull request as ready for review July 28, 2026 18:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant