Repository: go
Issue: runtime: frame pointer unwinding can fail on system goroutines
Labels: NeedsInvestigation,compiler/runtime

### What version of Go are you using (`go version`)?

<pre>
$ go version
go version devel go1.22-30d02e4925
</pre>

### Does this issue reproduce with the latest release?

Not exactly since we don't use frame pointer unwinding in this situation in any release.
However I believe the underlying issue is there in the latest release

### What operating system and processor architecture are you using (`go env`)?

<details><summary><code>go env</code> Output</summary><br><pre>
$ go env
GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/home/ec2-user/.cache/go-build'
GOENV='/home/ec2-user/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/ec2-user/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/ec2-user/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/home/ec2-user/repo/go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/home/ec2-user/repo/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='devel go1.22-30d02e4925 Fri Oct 6 13:02:40 2023 -0400'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/home/ec2-user/repo/go/src/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build1576787342=/tmp/go-build -gno-record-gcc-switches'
</pre></details>

### What did you do?

Attempted to use frame pointer unwinding to collect call stacks for the memory profiler. The motivation was in part to bring the efficiency gains we got for execution tracing to other places, but also to make frame pointers more widely used and thus more well-tested and reliable for the situations where we really want it to work. I observed this with [patchset 1 of this CL](https://go-review.googlesource.com/c/go/+/533258/1) and could reproduce it locally with `env GODEBUG=memprofilerate=1 go test ./runtime`.

### What did you expect to see?

Frame pointer unwinding to not fail.

### What did you see instead?

Frame pointer unwinding fails (crashing) when collecting memory profile samples:

```
SIGSEGV: segmentation violation
PC=0x4346d2 m=3 sigcode=2 addr=0x7fe60a5be288

goroutine 0 [idle]:
runtime.fpTracebackPCs(...)
        /home/ec2-user/repo/go/src/runtime/trace.go:1018
runtime.mProf_Malloc(0xc000080000, 0x580)
        /home/ec2-user/repo/go/src/runtime/mprof.go:432 +0x212 fp=0x7fe60afbdc20 sp=0x7fe60afbda98 pc=0x4346d2
runtime.profilealloc(0xc000080000?, 0x580?, 0x578?)
        /home/ec2-user/repo/go/src/runtime/malloc.go:1358 +0x79 fp=0x7fe60afbdc58 sp=0x7fe60afbdc20 pc=0x411bd9
runtime.mallocgc(0x578, 0x8610c0, 0x1)
        /home/ec2-user/repo/go/src/runtime/malloc.go:1206 +0x685 fp=0x7fe60afbdcc0 sp=0x7fe60afbdc58 pc=0x411785
runtime.newobject(0x0?)
        /home/ec2-user/repo/go/src/runtime/malloc.go:1322 +0x25 fp=0x7fe60afbdce8 sp=0x7fe60afbdcc0 pc=0x411aa5
runtime.allocm(0xc000036a00, 0x891888, 0x0?)
        /home/ec2-user/repo/go/src/runtime/proc.go:1934 +0x91 fp=0x7fe60afbdd40 sp=0x7fe60afbdce8 pc=0x443f71
runtime.newm(0x161604c4b3d4da?, 0xc000036a00, 0x0?)
        /home/ec2-user/repo/go/src/runtime/proc.go:2384 +0x35 fp=0x7fe60afbdd70 sp=0x7fe60afbdd40 pc=0x444895
runtime.startm(0xc000036a00?, 0x1, 0x0)
        /home/ec2-user/repo/go/src/runtime/proc.go:2610 +0x158 fp=0x7fe60afbddc0 sp=0x7fe60afbdd70 pc=0x444f78
runtime.wakep()
        /home/ec2-user/repo/go/src/runtime/proc.go:2746 +0xec fp=0x7fe60afbddf0 sp=0x7fe60afbddc0 pc=0x44550c
runtime.resetspinning()
        /home/ec2-user/repo/go/src/runtime/proc.go:3473 +0x3e fp=0x7fe60afbde10 sp=0x7fe60afbddf0 pc=0x4471fe
runtime.schedule()
        /home/ec2-user/repo/go/src/runtime/proc.go:3607 +0x10f fp=0x7fe60afbde48 sp=0x7fe60afbde10 pc=0x44762f
runtime.mstart1()
        /home/ec2-user/repo/go/src/runtime/proc.go:1608 +0xcd fp=0x7fe60afbde70 sp=0x7fe60afbde48 pc=0x4437ed
runtime.mstart0()
        /home/ec2-user/repo/go/src/runtime/proc.go:1558 +0x76 fp=0x7fe60afbdea0 sp=0x7fe60afbde70 pc=0x4436f6
runtime.mstart()
        /home/ec2-user/repo/go/src/runtime/asm_amd64.s:395 +0x5 fp=0x7fe60afbdea8 sp=0x7fe60afbdea0 pc=0x479b65
```

The unwinding fails after visiting the `mstart` frame. This is the entry point of the M. This function has a `TOPFRAME` annotation, which helps unwinders using DWARF know not to proceed, but doesn't help for frame pointer unwinding. Should we could modify the `mstart` implementations to explicitly set the frame pointer register to 0 on architectures with frame pointers? That resolves this failure, at least. We could also teach the assembler to do that when it sees `TOPFRAME` annotations.