Skip to content

Commit f758d64

Browse files
committed
runtime: implement traceback iterator
Currently, all stack walking logic is in one venerable, large, and very, very complicated function: runtime.gentraceback. This function has three distinct operating modes: printing, populating a PC buffer, or invoking a callback. And it has three different modes of unwinding: physical Go frames, inlined Go frames, and cgo frames. It also has several flags. All of this logic is very interwoven. This CL reimplements the monolithic gentraceback function as an "unwinder" type with an iterator API. It moves all of the logic for stack walking into this new type, and gentraceback is now a much-simplified wrapper around the new unwinder type that still implements printing, populating a PC buffer, and invoking a callback. Follow-up CLs will replace uses of gentraceback with direct uses of unwinder. Exposing traceback functionality as an iterator API will enable a lot of follow-up work such as simplifying the open-coded defer implementation (which should in turn help with #26813 and #37233), printing the bottom of deep stacks (#7181), and eliminating the small limit on CPU stacks in profiles (#56029). Fixes #54466. Change-Id: I36e046dc423c9429c4f286d47162af61aff49a0d Reviewed-on: https://go-review.googlesource.com/c/go/+/458218 Reviewed-by: Michael Pratt <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Run-TryBot: Austin Clements <[email protected]>
1 parent 86b69ef commit f758d64

File tree

4 files changed

+500
-318
lines changed

4 files changed

+500
-318
lines changed

src/runtime/crash_unix_test.go

+6-4
Original file line numberDiff line numberDiff line change
@@ -198,10 +198,12 @@ func TestPanicSystemstack(t *testing.T) {
198198

199199
// Traceback should have two testPanicSystemstackInternal's
200200
// and two blockOnSystemStackInternal's.
201-
if bytes.Count(tb, []byte("testPanicSystemstackInternal")) != 2 {
202-
t.Fatal("traceback missing user stack:\n", string(tb))
203-
} else if bytes.Count(tb, []byte("blockOnSystemStackInternal")) != 2 {
204-
t.Fatal("traceback missing system stack:\n", string(tb))
201+
userFunc := "testPanicSystemstackInternal"
202+
sysFunc := "blockOnSystemStackInternal"
203+
nUser := bytes.Count(tb, []byte(userFunc))
204+
nSys := bytes.Count(tb, []byte(sysFunc))
205+
if nUser != 2 || nSys != 2 {
206+
t.Fatalf("want %d user stack frames in %s and %d system stack frames in %s, got %d and %d:\n%s", 2, userFunc, 2, sysFunc, nUser, nSys, string(tb))
205207
}
206208
}
207209

src/runtime/runtime2.go

+8
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package runtime
77
import (
88
"internal/goarch"
99
"runtime/internal/atomic"
10+
"runtime/internal/sys"
1011
"unsafe"
1112
)
1213

@@ -270,6 +271,11 @@ func (gp *guintptr) cas(old, new guintptr) bool {
270271
return atomic.Casuintptr((*uintptr)(unsafe.Pointer(gp)), uintptr(old), uintptr(new))
271272
}
272273

274+
//go:nosplit
275+
func (gp *g) guintptr() guintptr {
276+
return guintptr(unsafe.Pointer(gp))
277+
}
278+
273279
// setGNoWB performs *gp = new without a write barrier.
274280
// For times when it's impractical to use a guintptr.
275281
//
@@ -881,6 +887,8 @@ const (
881887
// Keep in sync with linker (../cmd/link/internal/ld/pcln.go:/pclntab)
882888
// and with package debug/gosym and with symtab.go in package runtime.
883889
type _func struct {
890+
sys.NotInHeap // Only in static data
891+
884892
entryOff uint32 // start pc, as offset from moduledata.text/pcHeader.textStart
885893
nameOff int32 // function name, as index into moduledata.funcnametab.
886894

src/runtime/symtab.go

+2
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,8 @@ type pcHeader struct {
414414
// moduledata is stored in statically allocated non-pointer memory;
415415
// none of the pointers here are visible to the garbage collector.
416416
type moduledata struct {
417+
sys.NotInHeap // Only in static data
418+
417419
pcHeader *pcHeader
418420
funcnametab []byte
419421
cutab []uint32

0 commit comments

Comments
 (0)