go: runtime: running with delve on arm64 throws nosplit stack over 792 byte limit

What version of Go are you using (go version)?

tip

Does this issue reproduce with the latest release?

Only tip

What operating system and processor architecture are you using (go env)?

darwin/arm64

What did you do?

dlv debug cmd/go # any go program if that matters

What did you expect to see?

delve starts up

What did you see instead?

syscall.ptrace: nosplit stack over 792 byte limit
syscall.ptrace<1>
    grows 80 bytes, calls syscall.ptrace1<1>
        grows 160 bytes, calls syscall.syscall6<1>
            grows 192 bytes, calls runtime.exitsyscall<1>
                grows 96 bytes, calls runtime.exitsyscallfast<1>
                    grows 80 bytes, calls runtime.wirep<1>
                        grows 64 bytes, calls runtime.throw<1>
                            grows 48 bytes, calls runtime.fatalthrow<1>
                                grows 64 bytes, calls runtime.systemstack<0>
                                    grows 16 bytes, calls indirect
                                        grows 0 bytes, calls runtime.morestack<0>
                                        8 bytes over limit
                                    grows 16 bytes, calls runtime.abort<0>
                                    8 bytes over limit
                                    grows 16 bytes, calls gosave_systemstack_switch<22>
                                        grows 0 bytes, calls runtime.abort<0>
                                        8 bytes over limit
                                    grows 16 bytes, calls runtime.save_g<0>
                                    8 bytes over limit
                                    grows 16 bytes, calls indirect
                                        grows 0 bytes, calls runtime.morestack<0>
                                        8 bytes over limit
                                    grows 16 bytes, calls runtime.save_g<0>
                                    8 bytes over limit
                        grows 64 bytes, calls runtime.throw<1>
                            grows 48 bytes, calls runtime.fatalthrow<1>
                                grows 64 bytes, calls runtime.systemstack<0>
                                    grows 16 bytes, calls indirect
                                        grows 0 bytes, calls runtime.morestack<0>
                                        8 bytes over limit
                                    grows 16 bytes, calls runtime.abort<0>
                                    8 bytes over limit
                                    grows 16 bytes, calls gosave_systemstack_switch<22>
                                        grows 0 bytes, calls runtime.abort<0>
                                        8 bytes over limit
                                    grows 16 bytes, calls runtime.save_g<0>
                                    8 bytes over limit
                                    grows 16 bytes, calls indirect
                                        grows 0 bytes, calls runtime.morestack<0>
                                        8 bytes over limit
                                    grows 16 bytes, calls runtime.save_g<0>
                                    8 bytes over limit
exit status 1

This was introduced by CL 494187. Based on the comments there and my short investigation it appears that what is causing this is the new tracer allocated on the stack in exitsyscall.

cc @mknyszek

About this issue

  • Original URL
  • State: closed
  • Created 8 months ago
  • Reactions: 1
  • Comments: 15 (11 by maintainers)

Commits related to this issue

Most upvoted comments

CL https://go.dev/cl/545276 eliminates the ptrace1 frame, which should save ~80 bytes. I think this should get us back to under the limit. I tried building cmd/go with -N -l and it doesn’t overflow.

In the next cycle maybe we’ll make -N less aggressive on nosplit functions, while keeping a reasonable debugging experience.

I think this should be fixed now as of Cherry’s fix (not mine).

@mauri870 Thanks. Unfortunately that patch doesn’t help because nowfunc also needs to be nosplit. If the call to nowfunc tries to grow the stack, then something could break at runtime.

Running nanotime on the system stack is fine and would fix it, but may impact performance. I don’t see an easy solution yet; I’ll keep thinking.

Sorry for the delay here. We discussed this offline last week and I have a path forward, just haven’t gotten around to it. I’ll send a change to fix this today.

I can reproduce that with a simple go build without delve:

CGO_ENABLED=0 GOEXPERIMENTS=arenas GOOS=darwin GOARCH=arm64 gotip build -tags sql_scanner -gcflags="all=-N -l" -pgo=auto -ldflags ' -X github.com/xxxxxx/yyyyyy/cmd.Version=1a8f599-dirty -extldflags ""' -o dist/yyyyyy-1a8f599-dirty \
	./cmd/yyyyyy
# github.com/xxxxxxx/yyyyyy/cmd/yyyyyy
syscall.ptrace: nosplit stack over 792 byte limit
syscall.ptrace<1>
    grows 80 bytes, calls syscall.ptrace1<1>
        grows 160 bytes, calls syscall.syscall6<1>
            grows 192 bytes, calls runtime.entersyscall<1>
                grows 32 bytes, calls runtime.reentersyscall<1>
                    grows 112 bytes, calls runtime.casgstatus<1>
                        grows 80 bytes, calls runtime.nanotime<1>
                            grows 32 bytes, calls runtime.nanotime1<0>
                                grows 48 bytes, calls runtime.libcCall<1>
                                    grows 48 bytes, calls runtime.asmcgocall<0>
                                        grows 16 bytes, calls gosave_systemstack_switch<20>
...

Thanks for filing a bug; I’m aware of this issue but forgot to write it down. I’ll fix this before the release candidate.