src/runtime/panic.go GO 1,790 lines View on github.com → Search inside
1// Copyright 2014 The Go Authors. All rights reserved.2// Use of this source code is governed by a BSD-style3// license that can be found in the LICENSE file.45package runtime67import (8	"internal/abi"9	"internal/goarch"10	"internal/runtime/atomic"11	"internal/runtime/sys"12	"internal/stringslite"13	"unsafe"14)1516// throwType indicates the current type of ongoing throw, which affects the17// amount of detail printed to stderr. Higher values include more detail.18type throwType uint321920const (21	// throwTypeNone means that we are not throwing.22	throwTypeNone throwType = iota2324	// throwTypeUser is a throw due to a problem with the application.25	//26	// These throws do not include runtime frames, system goroutines, or27	// frame metadata.28	throwTypeUser2930	// throwTypeRuntime is a throw due to a problem with Go itself.31	//32	// These throws include as much information as possible to aid in33	// debugging the runtime, including runtime frames, system goroutines,34	// and frame metadata.35	throwTypeRuntime36)3738// We have two different ways of doing defers. The older way involves creating a39// defer record at the time that a defer statement is executing and adding it to a40// defer chain. This chain is inspected by the deferreturn call at all function41// exits in order to run the appropriate defer calls. A cheaper way (which we call42// open-coded defers) is used for functions in which no defer statements occur in43// loops. In that case, we simply store the defer function/arg information into44// specific stack slots at the point of each defer statement, as well as setting a45// bit in a bitmask. At each function exit, we add inline code to directly make46// the appropriate defer calls based on the bitmask and fn/arg information stored47// on the stack. During panic/Goexit processing, the appropriate defer calls are48// made using extra funcdata info that indicates the exact stack slots that49// contain the bitmask and defer fn/args.5051// Check to make sure we can really generate a panic. If the panic52// was generated from the runtime, or from inside malloc, then convert53// to a throw of msg.54// pc should be the program counter of the compiler-generated code that55// triggered this panic.56func panicCheck1(pc uintptr, msg string) {57	if goarch.IsWasm == 0 && stringslite.HasPrefix(funcname(findfunc(pc)), "runtime.") {58		// Note: wasm can't tail call, so we can't get the original caller's pc.59		throw(msg)60	}61	// TODO: is this redundant? How could we be in malloc62	// but not in the runtime? internal/runtime/*, maybe?63	gp := getg()64	if gp != nil && gp.m != nil && gp.m.mallocing != 0 {65		throw(msg)66	}67}6869// Same as above, but calling from the runtime is allowed.70//71// Using this function is necessary for any panic that may be72// generated by runtime.sigpanic, since those are always called by the73// runtime.74func panicCheck2(err string) {75	// panic allocates, so to avoid recursive malloc, turn panics76	// during malloc into throws.77	gp := getg()78	if gp != nil && gp.m != nil && gp.m.mallocing != 0 {79		throw(err)80	}81}8283// Many of the following panic entry-points turn into throws when they84// happen in various runtime contexts. These should never happen in85// the runtime, and if they do, they indicate a serious issue and86// should not be caught by user code.87//88// The panic{Index,Slice,divide,shift} functions are called by89// code generated by the compiler for out of bounds index expressions,90// out of bounds slice expressions, division by zero, and shift by negative.91// The panicdivide (again), panicoverflow, panicfloat, and panicmem92// functions are called by the signal handler when a signal occurs93// indicating the respective problem.94//95// Since panic{Index,Slice,shift} are never called directly, and96// since the runtime package should never have an out of bounds slice97// or array reference or negative shift, if we see those functions called from the98// runtime package we turn the panic into a throw. That will dump the99// entire runtime stack for easier debugging.100//101// The entry points called by the signal handler will be called from102// runtime.sigpanic, so we can't disallow calls from the runtime to103// these (they always look like they're called from the runtime).104// Hence, for these, we just check for clearly bad runtime conditions.105//106// The goPanic{Index,Slice} functions are only used by wasm. All the other architectures107// use panic{Bounds,Extend} in assembly, which then call to panicBounds{64,32,32X}.108109// failures in the comparisons for s[x], 0 <= x < y (y == len(s))110//111//go:yeswritebarrierrec112func goPanicIndex(x int, y int) {113	panicCheck1(sys.GetCallerPC(), "index out of range")114	panic(boundsError{x: int64(x), signed: true, y: y, code: abi.BoundsIndex})115}116117//go:yeswritebarrierrec118func goPanicIndexU(x uint, y int) {119	panicCheck1(sys.GetCallerPC(), "index out of range")120	panic(boundsError{x: int64(x), signed: false, y: y, code: abi.BoundsIndex})121}122123// failures in the comparisons for s[:x], 0 <= x <= y (y == len(s) or cap(s))124//125//go:yeswritebarrierrec126func goPanicSliceAlen(x int, y int) {127	panicCheck1(sys.GetCallerPC(), "slice bounds out of range")128	panic(boundsError{x: int64(x), signed: true, y: y, code: abi.BoundsSliceAlen})129}130131//go:yeswritebarrierrec132func goPanicSliceAlenU(x uint, y int) {133	panicCheck1(sys.GetCallerPC(), "slice bounds out of range")134	panic(boundsError{x: int64(x), signed: false, y: y, code: abi.BoundsSliceAlen})135}136137//go:yeswritebarrierrec138func goPanicSliceAcap(x int, y int) {139	panicCheck1(sys.GetCallerPC(), "slice bounds out of range")140	panic(boundsError{x: int64(x), signed: true, y: y, code: abi.BoundsSliceAcap})141}142143//go:yeswritebarrierrec144func goPanicSliceAcapU(x uint, y int) {145	panicCheck1(sys.GetCallerPC(), "slice bounds out of range")146	panic(boundsError{x: int64(x), signed: false, y: y, code: abi.BoundsSliceAcap})147}148149// failures in the comparisons for s[x:y], 0 <= x <= y150//151//go:yeswritebarrierrec152func goPanicSliceB(x int, y int) {153	panicCheck1(sys.GetCallerPC(), "slice bounds out of range")154	panic(boundsError{x: int64(x), signed: true, y: y, code: abi.BoundsSliceB})155}156157//go:yeswritebarrierrec158func goPanicSliceBU(x uint, y int) {159	panicCheck1(sys.GetCallerPC(), "slice bounds out of range")160	panic(boundsError{x: int64(x), signed: false, y: y, code: abi.BoundsSliceB})161}162163// failures in the comparisons for s[::x], 0 <= x <= y (y == len(s) or cap(s))164func goPanicSlice3Alen(x int, y int) {165	panicCheck1(sys.GetCallerPC(), "slice bounds out of range")166	panic(boundsError{x: int64(x), signed: true, y: y, code: abi.BoundsSlice3Alen})167}168func goPanicSlice3AlenU(x uint, y int) {169	panicCheck1(sys.GetCallerPC(), "slice bounds out of range")170	panic(boundsError{x: int64(x), signed: false, y: y, code: abi.BoundsSlice3Alen})171}172func goPanicSlice3Acap(x int, y int) {173	panicCheck1(sys.GetCallerPC(), "slice bounds out of range")174	panic(boundsError{x: int64(x), signed: true, y: y, code: abi.BoundsSlice3Acap})175}176func goPanicSlice3AcapU(x uint, y int) {177	panicCheck1(sys.GetCallerPC(), "slice bounds out of range")178	panic(boundsError{x: int64(x), signed: false, y: y, code: abi.BoundsSlice3Acap})179}180181// failures in the comparisons for s[:x:y], 0 <= x <= y182func goPanicSlice3B(x int, y int) {183	panicCheck1(sys.GetCallerPC(), "slice bounds out of range")184	panic(boundsError{x: int64(x), signed: true, y: y, code: abi.BoundsSlice3B})185}186func goPanicSlice3BU(x uint, y int) {187	panicCheck1(sys.GetCallerPC(), "slice bounds out of range")188	panic(boundsError{x: int64(x), signed: false, y: y, code: abi.BoundsSlice3B})189}190191// failures in the comparisons for s[x:y:], 0 <= x <= y192func goPanicSlice3C(x int, y int) {193	panicCheck1(sys.GetCallerPC(), "slice bounds out of range")194	panic(boundsError{x: int64(x), signed: true, y: y, code: abi.BoundsSlice3C})195}196func goPanicSlice3CU(x uint, y int) {197	panicCheck1(sys.GetCallerPC(), "slice bounds out of range")198	panic(boundsError{x: int64(x), signed: false, y: y, code: abi.BoundsSlice3C})199}200201// failures in the conversion ([x]T)(s) or (*[x]T)(s), 0 <= x <= y, y == len(s)202func goPanicSliceConvert(x int, y int) {203	panicCheck1(sys.GetCallerPC(), "slice length too short to convert to array or pointer to array")204	panic(boundsError{x: int64(x), signed: true, y: y, code: abi.BoundsConvert})205}206207// Implemented in assembly. Declared here to mark them as ABIInternal.208func panicBounds() // in asm_GOARCH.s files, called from generated code209func panicExtend() // in asm_GOARCH.s files, called from generated code (on 32-bit archs)210211func panicBounds64(pc uintptr, regs *[16]int64) { // called from panicBounds on 64-bit archs212	f := findfunc(pc)213	v := pcdatavalue(f, abi.PCDATA_PanicBounds, pc-1)214215	code, signed, xIsReg, yIsReg, xVal, yVal := abi.BoundsDecode(int(v))216217	if code == abi.BoundsIndex {218		panicCheck1(pc, "index out of range")219	} else {220		panicCheck1(pc, "slice bounds out of range")221	}222223	var e boundsError224	e.code = code225	e.signed = signed226	if xIsReg {227		e.x = regs[xVal]228	} else {229		e.x = int64(xVal)230	}231	if yIsReg {232		e.y = int(regs[yVal])233	} else {234		e.y = yVal235	}236	panic(e)237}238239func panicBounds32(pc uintptr, regs *[16]int32) { // called from panicBounds on 32-bit archs240	f := findfunc(pc)241	v := pcdatavalue(f, abi.PCDATA_PanicBounds, pc-1)242243	code, signed, xIsReg, yIsReg, xVal, yVal := abi.BoundsDecode(int(v))244245	if code == abi.BoundsIndex {246		panicCheck1(pc, "index out of range")247	} else {248		panicCheck1(pc, "slice bounds out of range")249	}250251	var e boundsError252	e.code = code253	e.signed = signed254	if xIsReg {255		if signed {256			e.x = int64(regs[xVal])257		} else {258			e.x = int64(uint32(regs[xVal]))259		}260	} else {261		e.x = int64(xVal)262	}263	if yIsReg {264		e.y = int(regs[yVal])265	} else {266		e.y = yVal267	}268	panic(e)269}270271func panicBounds32X(pc uintptr, regs *[16]int32) { // called from panicExtend on 32-bit archs272	f := findfunc(pc)273	v := pcdatavalue(f, abi.PCDATA_PanicBounds, pc-1)274275	code, signed, xIsReg, yIsReg, xVal, yVal := abi.BoundsDecode(int(v))276277	if code == abi.BoundsIndex {278		panicCheck1(pc, "index out of range")279	} else {280		panicCheck1(pc, "slice bounds out of range")281	}282283	var e boundsError284	e.code = code285	e.signed = signed286	if xIsReg {287		// Our 4-bit register numbers are actually 2 2-bit register numbers.288		lo := xVal & 3289		hi := xVal >> 2290		e.x = int64(regs[hi])<<32 + int64(uint32(regs[lo]))291	} else {292		e.x = int64(xVal)293	}294	if yIsReg {295		e.y = int(regs[yVal])296	} else {297		e.y = yVal298	}299	panic(e)300}301302var shiftError = error(errorString("negative shift amount"))303304//go:yeswritebarrierrec305func panicshift() {306	panicCheck1(sys.GetCallerPC(), "negative shift amount")307	panic(shiftError)308}309310var divideError = error(errorString("integer divide by zero"))311312//go:yeswritebarrierrec313func panicdivide() {314	panicCheck2("integer divide by zero")315	panic(divideError)316}317318var overflowError = error(errorString("integer overflow"))319320func panicoverflow() {321	panicCheck2("integer overflow")322	panic(overflowError)323}324325var floatError = error(errorString("floating point error"))326327func panicfloat() {328	panicCheck2("floating point error")329	panic(floatError)330}331332var memoryError = error(errorString("invalid memory address or nil pointer dereference"))333334func panicmem() {335	panicCheck2("invalid memory address or nil pointer dereference")336	panic(memoryError)337}338339func panicmemAddr(addr uintptr) {340	panicCheck2("invalid memory address or nil pointer dereference")341	panic(errorAddressString{msg: "invalid memory address or nil pointer dereference", addr: addr})342}343344var simdImmError = error(errorString("out-of-range immediate for simd intrinsic"))345346func panicSimdImm() {347	panicCheck2("simd immediate error")348	panic(simdImmError)349}350351// Create a new deferred function fn, which has no arguments and results.352// The compiler turns a defer statement into a call to this.353func deferproc(fn func()) {354	gp := getg()355	if gp.m.curg != gp {356		// go code on the system stack can't defer357		throw("defer on system stack")358	}359360	d := newdefer()361	d.link = gp._defer362	gp._defer = d363	d.fn = fn364	d.pc = sys.GetCallerPC()365	// We must not be preempted between calling GetCallerSP and366	// storing it to d.sp because GetCallerSP's result is a367	// uintptr stack pointer.368	d.sp = sys.GetCallerSP()369}370371var rangeDoneError = error(errorString("range function continued iteration after function for loop body returned false"))372var rangePanicError = error(errorString("range function continued iteration after loop body panic"))373var rangeExhaustedError = error(errorString("range function continued iteration after whole loop exit"))374var rangeMissingPanicError = error(errorString("range function recovered a loop body panic and did not resume panicking"))375376//go:noinline377func panicrangestate(state int) {378	switch abi.RF_State(state) {379	case abi.RF_DONE:380		panic(rangeDoneError)381	case abi.RF_PANIC:382		panic(rangePanicError)383	case abi.RF_EXHAUSTED:384		panic(rangeExhaustedError)385	case abi.RF_MISSING_PANIC:386		panic(rangeMissingPanicError)387	}388	throw("unexpected state passed to panicrangestate")389}390391// deferrangefunc is called by functions that are about to392// execute a range-over-function loop in which the loop body393// may execute a defer statement. That defer needs to add to394// the chain for the current function, not the func literal synthesized395// to represent the loop body. To do that, the original function396// calls deferrangefunc to obtain an opaque token representing397// the current frame, and then the loop body uses deferprocat398// instead of deferproc to add to that frame's defer lists.399//400// The token is an 'any' with underlying type *atomic.Pointer[_defer].401// It is the atomically-updated head of a linked list of _defer structs402// representing deferred calls. At the same time, we create a _defer403// struct on the main g._defer list with d.head set to this head pointer.404//405// The g._defer list is now a linked list of deferred calls,406// but an atomic list hanging off:407//408//		g._defer => d4 -> d3 -> drangefunc -> d2 -> d1 -> nil409//	                             | .head410//	                             |411//	                             +--> dY -> dX -> nil412//413// with each -> indicating a d.link pointer, and where drangefunc414// has the d.rangefunc = true bit set.415// Note that the function being ranged over may have added416// its own defers (d4 and d3), so drangefunc need not be at the417// top of the list when deferprocat is used. This is why we pass418// the atomic head explicitly.419//420// To keep misbehaving programs from crashing the runtime,421// deferprocat pushes new defers onto the .head list atomically.422// The fact that it is a separate list from the main goroutine423// defer list means that the main goroutine's defers can still424// be handled non-atomically.425//426// In the diagram, dY and dX are meant to be processed when427// drangefunc would be processed, which is to say the defer order428// should be d4, d3, dY, dX, d2, d1. To make that happen,429// when defer processing reaches a d with rangefunc=true,430// it calls deferconvert to atomically take the extras431// away from d.head and then adds them to the main list.432//433// That is, deferconvert changes this list:434//435//		g._defer => drangefunc -> d2 -> d1 -> nil436//	                 | .head437//	                 |438//	                 +--> dY -> dX -> nil439//440// into this list:441//442//	g._defer => dY -> dX -> d2 -> d1 -> nil443//444// It also poisons *drangefunc.head so that any future445// deferprocat using that head will throw.446// (The atomic head is ordinary garbage collected memory so that447// it's not a problem if user code holds onto it beyond448// the lifetime of drangefunc.)449//450// TODO: We could arrange for the compiler to call into the451// runtime after the loop finishes normally, to do an eager452// deferconvert, which would catch calling the loop body453// and having it defer after the loop is done. If we have a454// more general catch of loop body misuse, though, this455// might not be worth worrying about in addition.456//457// See also ../cmd/compile/internal/rangefunc/rewrite.go.458func deferrangefunc() any {459	gp := getg()460	if gp.m.curg != gp {461		// go code on the system stack can't defer462		throw("defer on system stack")463	}464465	d := newdefer()466	d.link = gp._defer467	gp._defer = d468	d.pc = sys.GetCallerPC()469	// We must not be preempted between calling GetCallerSP and470	// storing it to d.sp because GetCallerSP's result is a471	// uintptr stack pointer.472	d.sp = sys.GetCallerSP()473474	d.rangefunc = true475	d.head = new(atomic.Pointer[_defer])476477	return d.head478}479480// badDefer returns a fixed bad defer pointer for poisoning an atomic defer list head.481func badDefer() *_defer {482	return (*_defer)(unsafe.Pointer(uintptr(1)))483}484485// deferprocat is like deferproc but adds to the atomic list represented by frame.486// See the doc comment for deferrangefunc for details.487func deferprocat(fn func(), frame any) {488	head := frame.(*atomic.Pointer[_defer])489	if raceenabled {490		racewritepc(unsafe.Pointer(head), sys.GetCallerPC(), abi.FuncPCABIInternal(deferprocat))491	}492	d1 := newdefer()493	d1.fn = fn494	for {495		d1.link = head.Load()496		if d1.link == badDefer() {497			throw("defer after range func returned")498		}499		if head.CompareAndSwap(d1.link, d1) {500			break501		}502	}503}504505// deferconvert converts the rangefunc defer list of d0 into an ordinary list506// following d0.507// See the doc comment for deferrangefunc for details.508func deferconvert(d0 *_defer) {509	head := d0.head510	if raceenabled {511		racereadpc(unsafe.Pointer(head), sys.GetCallerPC(), abi.FuncPCABIInternal(deferconvert))512	}513	tail := d0.link514	d0.rangefunc = false515516	var d *_defer517	for {518		d = head.Load()519		if head.CompareAndSwap(d, badDefer()) {520			break521		}522	}523	if d == nil {524		return525	}526	for d1 := d; ; d1 = d1.link {527		d1.sp = d0.sp528		d1.pc = d0.pc529		if d1.link == nil {530			d1.link = tail531			break532		}533	}534	d0.link = d535	return536}537538// deferprocStack queues a new deferred function with a defer record on the stack.539// The defer record must have its fn field initialized.540// All other fields can contain junk.541// Nosplit because of the uninitialized pointer fields on the stack.542//543//go:nosplit544func deferprocStack(d *_defer) {545	gp := getg()546	if gp.m.curg != gp {547		// go code on the system stack can't defer548		throw("defer on system stack")549	}550551	// fn is already set.552	// The other fields are junk on entry to deferprocStack and553	// are initialized here.554	d.heap = false555	d.rangefunc = false556	d.sp = sys.GetCallerSP()557	d.pc = sys.GetCallerPC()558	// The lines below implement:559	//   d.link = gp._defer560	//   d.head = nil561	//   gp._defer = d562	// But without write barriers. The first two are writes to563	// the stack so they don't need a write barrier, and furthermore564	// are to uninitialized memory, so they must not use a write barrier.565	// The third write does not require a write barrier because we566	// explicitly mark all the defer structures, so we don't need to567	// keep track of pointers to them with a write barrier.568	*(*uintptr)(unsafe.Pointer(&d.link)) = uintptr(unsafe.Pointer(gp._defer))569	*(*uintptr)(unsafe.Pointer(&d.head)) = 0570	*(*uintptr)(unsafe.Pointer(&gp._defer)) = uintptr(unsafe.Pointer(d))571}572573// Each P holds a pool for defers.574575// Allocate a Defer, usually using per-P pool.576// Each defer must be released with freedefer.  The defer is not577// added to any defer chain yet.578func newdefer() *_defer {579	var d *_defer580	mp := acquirem()581	pp := mp.p.ptr()582	if len(pp.deferpool) == 0 && sched.deferpool != nil {583		lock(&sched.deferlock)584		for len(pp.deferpool) < cap(pp.deferpool)/2 && sched.deferpool != nil {585			d := sched.deferpool586			sched.deferpool = d.link587			d.link = nil588			pp.deferpool = append(pp.deferpool, d)589		}590		unlock(&sched.deferlock)591	}592	if n := len(pp.deferpool); n > 0 {593		d = pp.deferpool[n-1]594		pp.deferpool[n-1] = nil595		pp.deferpool = pp.deferpool[:n-1]596	}597	releasem(mp)598	mp, pp = nil, nil599600	if d == nil {601		// Allocate new defer.602		d = new(_defer)603	}604	d.heap = true605	return d606}607608// popDefer pops the head of gp's defer list and frees it.609func popDefer(gp *g) {610	d := gp._defer611	d.fn = nil // Can in theory point to the stack612	// We must not copy the stack between the updating gp._defer and setting613	// d.link to nil. Between these two steps, d is not on any defer list, so614	// stack copying won't adjust stack pointers in it (namely, d.link). Hence,615	// if we were to copy the stack, d could then contain a stale pointer.616	gp._defer = d.link617	d.link = nil618	// After this point we can copy the stack.619620	if !d.heap {621		return622	}623624	mp := acquirem()625	pp := mp.p.ptr()626	if len(pp.deferpool) == cap(pp.deferpool) {627		// Transfer half of local cache to the central cache.628		var first, last *_defer629		for len(pp.deferpool) > cap(pp.deferpool)/2 {630			n := len(pp.deferpool)631			d := pp.deferpool[n-1]632			pp.deferpool[n-1] = nil633			pp.deferpool = pp.deferpool[:n-1]634			if first == nil {635				first = d636			} else {637				last.link = d638			}639			last = d640		}641		lock(&sched.deferlock)642		last.link = sched.deferpool643		sched.deferpool = first644		unlock(&sched.deferlock)645	}646647	*d = _defer{}648649	pp.deferpool = append(pp.deferpool, d)650651	releasem(mp)652	mp, pp = nil, nil653}654655// deferreturn runs deferred functions for the caller's frame.656// The compiler inserts a call to this at the end of any657// function which calls defer.658func deferreturn() {659	var p _panic660	p.deferreturn = true661662	p.start(sys.GetCallerPC(), unsafe.Pointer(sys.GetCallerSP()))663	for {664		fn, ok := p.nextDefer()665		if !ok {666			break667		}668		fn()669	}670}671672// Goexit terminates the goroutine that calls it. No other goroutine is affected.673// Goexit runs all deferred calls before terminating the goroutine. Because Goexit674// is not a panic, any recover calls in those deferred functions will return nil.675//676// Calling Goexit from the main goroutine terminates that goroutine677// without func main returning. Since func main has not returned,678// the program continues execution of other goroutines.679// If all other goroutines exit, the program crashes.680//681// It crashes if called from a thread not created by the Go runtime.682func Goexit() {683	// Create a panic object for Goexit, so we can recognize when it might be684	// bypassed by a recover().685	var p _panic686	p.goexit = true687688	p.start(sys.GetCallerPC(), unsafe.Pointer(sys.GetCallerSP()))689	for {690		fn, ok := p.nextDefer()691		if !ok {692			break693		}694		fn()695	}696697	goexit1()698}699700// Call all Error and String methods before freezing the world.701// Used when crashing with panicking.702func preprintpanics(p *_panic) {703	defer func() {704		text := "panic while printing panic value"705		switch r := recover().(type) {706		case nil:707			// nothing to do708		case string:709			throw(text + ": " + r)710		default:711			throw(text + ": type " + toRType(efaceOf(&r)._type).string())712		}713	}()714	for p != nil {715		if p.link != nil && *efaceOf(&p.link.arg) == *efaceOf(&p.arg) {716			// This panic contains the same value as the next one in the chain.717			// Mark it as repanicked. We will skip printing it twice in a row.718			p.link.repanicked = true719			p = p.link720			continue721		}722		switch v := p.arg.(type) {723		case error:724			p.arg = v.Error()725		case stringer:726			p.arg = v.String()727		}728		p = p.link729	}730}731732// Print all currently active panics. Used when crashing.733// Should only be called after preprintpanics.734func printpanics(p *_panic) {735	if p.link != nil {736		printpanics(p.link)737		if p.link.repanicked {738			return739		}740		if !p.link.goexit {741			print("\t")742		}743	}744	if p.goexit {745		return746	}747	print("panic: ")748	printpanicval(p.arg)749	if p.recovered && p.repanicked {750		print(" [recovered, repanicked]")751	} else if p.recovered {752		print(" [recovered]")753	}754	print("\n")755}756757// readvarintUnsafe reads the uint32 in varint format starting at fd, and returns the758// uint32 and a pointer to the byte following the varint.759//760// The implementation is the same with runtime.readvarint, except that this function761// uses unsafe.Pointer for speed.762func readvarintUnsafe(fd unsafe.Pointer) (uint32, unsafe.Pointer) {763	var r uint32764	var shift int765	for {766		b := *(*uint8)(fd)767		fd = add(fd, unsafe.Sizeof(b))768		if b < 128 {769			return r + uint32(b)<<shift, fd770		}771		r += uint32(b&0x7F) << (shift & 31)772		shift += 7773		if shift > 28 {774			panic("Bad varint")775		}776	}777}778779// A PanicNilError happens when code calls panic(nil).780//781// Before Go 1.21, programs that called panic(nil) observed recover returning nil.782// Starting in Go 1.21, programs that call panic(nil) observe recover returning a *PanicNilError.783// Programs can change back to the old behavior by setting GODEBUG=panicnil=1.784type PanicNilError struct {785	// This field makes PanicNilError structurally different from786	// any other struct in this package, and the _ makes it different787	// from any struct in other packages too.788	// This avoids any accidental conversions being possible789	// between this struct and some other struct sharing the same fields,790	// like happened in go.dev/issue/56603.791	_ [0]*PanicNilError792}793794func (*PanicNilError) Error() string { return "runtime error: panic called with nil argument" }795func (*PanicNilError) RuntimeError() {}796797var panicnil = &godebugInc{name: "panicnil"}798799// The implementation of the predeclared function panic.800// The compiler emits calls to this function.801//802// gopanic should be an internal detail,803// but historically, widely used packages access it using linkname.804//805// Do not remove or change the type signature.806// See go.dev/issue/67401.807//808//go:linkname gopanic809func gopanic(e any) {810	if e == nil {811		if debug.panicnil.Load() != 1 {812			e = new(PanicNilError)813		} else {814			panicnil.IncNonDefault()815		}816	}817818	gp := getg()819	if gp.m.curg != gp {820		print("panic: ")821		printpanicval(e)822		print("\n")823		throw("panic on system stack")824	}825826	if gp.m.mallocing != 0 {827		print("panic: ")828		printpanicval(e)829		print("\n")830		throw("panic during malloc")831	}832	if gp.m.preemptoff != "" {833		print("panic: ")834		printpanicval(e)835		print("\n")836		print("preempt off reason: ")837		print(gp.m.preemptoff)838		print("\n")839		throw("panic during preemptoff")840	}841	if gp.m.locks != 0 {842		print("panic: ")843		printpanicval(e)844		print("\n")845		throw("panic holding locks")846	}847848	var p _panic849	p.arg = e850851	runningPanicDefers.Add(1)852853	p.start(sys.GetCallerPC(), unsafe.Pointer(sys.GetCallerSP()))854	for {855		fn, ok := p.nextDefer()856		if !ok {857			break858		}859		fn()860	}861862	// If we're tracing, flush the current generation to make the trace more863	// readable.864	//865	// TODO(aktau): Handle a panic from within traceAdvance more gracefully.866	// Currently it would hang. Not handled now because it is very unlikely, and867	// already unrecoverable.868	if traceEnabled() {869		traceAdvance(false)870	}871872	// ran out of deferred calls - old-school panic now873	// Because it is unsafe to call arbitrary user code after freezing874	// the world, we call preprintpanics to invoke all necessary Error875	// and String methods to prepare the panic strings before startpanic.876	preprintpanics(&p)877878	fatalpanic(&p)   // should not return879	*(*int)(nil) = 0 // not reached880}881882// start initializes a panic to start unwinding the stack.883//884// If p.goexit is true, then start may return multiple times.885func (p *_panic) start(pc uintptr, sp unsafe.Pointer) {886	gp := getg()887888	// Record the caller's PC and SP, so recovery can identify panics889	// that have been recovered. Also, so that if p is from Goexit, we890	// can restart its defer processing loop if a recovered panic tries891	// to jump past it.892	p.startPC = sys.GetCallerPC()893	p.startSP = unsafe.Pointer(sys.GetCallerSP())894895	if p.deferreturn {896		p.sp = sp897898		if s := (*savedOpenDeferState)(gp.param); s != nil {899			// recovery saved some state for us, so that we can resume900			// calling open-coded defers without unwinding the stack.901902			gp.param = nil903904			p.retpc = s.retpc905			p.deferBitsPtr = (*byte)(add(sp, s.deferBitsOffset))906			p.slotsPtr = add(sp, s.slotsOffset)907		}908909		return910	}911912	p.link = gp._panic913	gp._panic = (*_panic)(noescape(unsafe.Pointer(p)))914915	// Initialize state machine, and find the first frame with a defer.916	//917	// Note: We could use startPC and startSP here, but callers will918	// never have defer statements themselves. By starting at their919	// caller instead, we avoid needing to unwind through an extra920	// frame. It also somewhat simplifies the terminating condition for921	// deferreturn.922	p.pc, p.sp = pc, sp923	p.nextFrame()924}925926// nextDefer returns the next deferred function to invoke, if any.927//928// Note: The "ok bool" result is necessary to correctly handle when929// the deferred function itself was nil (e.g., "defer (func())(nil)").930func (p *_panic) nextDefer() (func(), bool) {931	gp := getg()932933	if !p.deferreturn {934		if gp._panic != p {935			throw("bad panic stack")936		}937938		if p.recovered {939			mcall(recovery) // does not return940			throw("recovery failed")941		}942	}943944	for {945		for p.deferBitsPtr != nil {946			bits := *p.deferBitsPtr947948			// Check whether any open-coded defers are still pending.949			//950			// Note: We need to check this upfront (rather than after951			// clearing the top bit) because it's possible that Goexit952			// invokes a deferred call, and there were still more pending953			// open-coded defers in the frame; but then the deferred call954			// panic and invoked the remaining defers in the frame, before955			// recovering and restarting the Goexit loop.956			if bits == 0 {957				p.deferBitsPtr = nil958				break959			}960961			// Find index of top bit set.962			i := 7 - uintptr(sys.LeadingZeros8(bits))963964			// Clear bit and store it back.965			bits &^= 1 << i966			*p.deferBitsPtr = bits967968			return *(*func())(add(p.slotsPtr, i*goarch.PtrSize)), true969		}970971	Recheck:972		if d := gp._defer; d != nil && d.sp == uintptr(p.sp) {973			if d.rangefunc {974				deferconvert(d)975				popDefer(gp)976				goto Recheck977			}978979			fn := d.fn980981			p.retpc = d.pc982983			// Unlink and free.984			popDefer(gp)985986			return fn, true987		}988989		if !p.nextFrame() {990			return nil, false991		}992	}993}994995// nextFrame finds the next frame that contains deferred calls, if any.996func (p *_panic) nextFrame() (ok bool) {997	if p.pc == 0 {998		return false999	}10001001	gp := getg()1002	systemstack(func() {1003		var limit uintptr1004		if d := gp._defer; d != nil {1005			limit = d.sp1006		}10071008		var u unwinder1009		u.initAt(p.pc, uintptr(p.sp), 0, gp, 0)1010		for {1011			if !u.valid() {1012				p.pc = 01013				return // ok == false1014			}10151016			// TODO(mdempsky): If we populate u.frame.fn.deferreturn for1017			// every frame containing a defer (not just open-coded defers),1018			// then we can simply loop until we find the next frame where1019			// it's non-zero.10201021			if u.frame.sp == limit {1022				break // found a frame with linked defers1023			}10241025			if p.initOpenCodedDefers(u.frame.fn, unsafe.Pointer(u.frame.varp)) {1026				break // found a frame with open-coded defers1027			}10281029			if p.link != nil && uintptr(u.frame.sp) == uintptr(p.link.startSP) && uintptr(p.link.sp) > u.frame.sp {1030				// Skip ahead to where the next panic up the stack was last looking1031				// for defers. See issue 77062.1032				//1033				// The startSP condition is to check when we have walked up the stack1034				// to where the next panic up the stack started. If so, the processing1035				// of that panic has run all the defers up to its current scanning1036				// position.1037				//1038				// The final condition is just to make sure that the line below1039				// is actually helpful.1040				u.initAt(p.link.pc, uintptr(p.link.sp), 0, gp, 0)1041				continue1042			}10431044			u.next()1045		}10461047		p.pc = u.frame.pc1048		p.sp = unsafe.Pointer(u.frame.sp)1049		p.fp = unsafe.Pointer(u.frame.fp)10501051		ok = true1052	})10531054	return1055}10561057func (p *_panic) initOpenCodedDefers(fn funcInfo, varp unsafe.Pointer) bool {1058	fd := funcdata(fn, abi.FUNCDATA_OpenCodedDeferInfo)1059	if fd == nil {1060		return false1061	}10621063	if fn.deferreturn == 0 {1064		throw("missing deferreturn")1065	}10661067	deferBitsOffset, fd := readvarintUnsafe(fd)1068	deferBitsPtr := (*uint8)(add(varp, -uintptr(deferBitsOffset)))1069	if *deferBitsPtr == 0 {1070		return false // has open-coded defers, but none pending1071	}10721073	slotsOffset, fd := readvarintUnsafe(fd)10741075	p.retpc = fn.entry() + uintptr(fn.deferreturn)1076	p.deferBitsPtr = deferBitsPtr1077	p.slotsPtr = add(varp, -uintptr(slotsOffset))10781079	return true1080}10811082// The implementation of the predeclared function recover.1083func gorecover() any {1084	gp := getg()1085	p := gp._panic1086	if p == nil || p.goexit || p.recovered {1087		return nil1088	}10891090	// Check to see if the function that called recover() was1091	// deferred directly from the panicking function.1092	// For code like:1093	//     func foo() {1094	//         defer bar()1095	//         panic("panic")1096	//     }1097	//     func bar() {1098	//         recover()1099	//     }1100	// Normally the stack would look like this:1101	//     foo1102	//     runtime.gopanic1103	//     bar1104	//     runtime.gorecover1105	//1106	// However, if the function we deferred requires a wrapper1107	// of some sort, we need to ignore the wrapper. In that case,1108	// the stack looks like:1109	//     foo1110	//     runtime.gopanic1111	//     wrapper1112	//     bar1113	//     runtime.gorecover1114	// And we should also successfully recover.1115	//1116	// Finally, in the weird case "defer recover()", the stack looks like:1117	//     foo1118	//     runtime.gopanic1119	//     wrapper1120	//     runtime.gorecover1121	// And we should not recover in that case.1122	//1123	// So our criteria is, there must be exactly one non-wrapper1124	// frame between gopanic and gorecover.1125	//1126	// We don't recover this:1127	//     defer func() { func() { recover() }() }()1128	// because there are 2 non-wrapper frames.1129	//1130	// We don't recover this:1131	//     defer recover()1132	// because there are 0 non-wrapper frames.1133	canRecover := false1134	systemstack(func() {1135		var u unwinder1136		u.init(gp, 0)1137		u.next() // skip systemstack_switch1138		u.next() // skip gorecover1139		nonWrapperFrames := 01140	loop:1141		for ; u.valid(); u.next() {1142			for iu, f := newInlineUnwinder(u.frame.fn, u.symPC()); f.valid(); f = iu.next(f) {1143				sf := iu.srcFunc(f)1144				switch sf.funcID {1145				case abi.FuncIDWrapper:1146					continue1147				case abi.FuncID_gopanic:1148					if u.frame.sp == uintptr(p.startSP) && nonWrapperFrames > 0 {1149						canRecover = true1150					}1151					break loop1152				default:1153					nonWrapperFrames++1154					if nonWrapperFrames > 1 {1155						break loop1156					}1157				}1158			}1159		}1160	})1161	if !canRecover {1162		return nil1163	}1164	p.recovered = true1165	return p.arg1166}11671168//go:linkname sync_throw sync.throw1169func sync_throw(s string) {1170	throw(s)1171}11721173//go:linkname sync_fatal sync.fatal1174func sync_fatal(s string) {1175	fatal(s)1176}11771178//go:linkname rand_fatal crypto/rand.fatal1179func rand_fatal(s string) {1180	fatal(s)1181}11821183//go:linkname sysrand_fatal crypto/internal/sysrand.fatal1184func sysrand_fatal(s string) {1185	fatal(s)1186}11871188//go:linkname fips_fatal crypto/internal/fips140.fatal1189func fips_fatal(s string) {1190	fatal(s)1191}11921193//go:linkname maps_fatal internal/runtime/maps.fatal1194func maps_fatal(s string) {1195	fatal(s)1196}11971198//go:linkname internal_sync_throw internal/sync.throw1199func internal_sync_throw(s string) {1200	throw(s)1201}12021203//go:linkname internal_sync_fatal internal/sync.fatal1204func internal_sync_fatal(s string) {1205	fatal(s)1206}12071208//go:linkname cgroup_throw internal/runtime/cgroup.throw1209func cgroup_throw(s string) {1210	throw(s)1211}12121213// throw triggers a fatal error that dumps a stack trace and exits.1214//1215// throw should be used for runtime-internal fatal errors where Go itself,1216// rather than user code, may be at fault for the failure.1217//1218// throw should be an internal detail,1219// but widely used packages access it using linkname.1220// Notable members of the hall of shame include:1221//   - github.com/bytedance/sonic1222//   - github.com/cockroachdb/pebble1223//   - github.com/dgraph-io/ristretto1224//   - github.com/outcaste-io/ristretto1225//   - github.com/pingcap/br1226//   - gvisor.dev/gvisor1227//   - github.com/sagernet/gvisor1228//1229// Do not remove or change the type signature.1230// See go.dev/issue/67401.1231//1232//go:linkname throw1233//go:nosplit1234func throw(s string) {1235	// Everything throw does should be recursively nosplit so it1236	// can be called even when it's unsafe to grow the stack.1237	systemstack(func() {1238		print("fatal error: ")1239		printindented(s) // logically printpanicval(s), but avoids convTstring write barrier1240		print("\n")1241	})12421243	fatalthrow(throwTypeRuntime)1244}12451246// fatal triggers a fatal error that dumps a stack trace and exits.1247//1248// fatal is equivalent to throw, but is used when user code is expected to be1249// at fault for the failure, such as racing map writes.1250//1251// fatal does not include runtime frames, system goroutines, or frame metadata1252// (fp, sp, pc) in the stack trace unless GOTRACEBACK=system or higher.1253//1254//go:nosplit1255func fatal(s string) {1256	p := getg()._panic1257	// Everything fatal does should be recursively nosplit so it1258	// can be called even when it's unsafe to grow the stack.1259	printlock() // Prevent multiple interleaved fatal reports. See issue 69447.1260	systemstack(func() {1261		printPreFatalDeferPanic(p)1262		print("fatal error: ")1263		printindented(s) // logically printpanicval(s), but avoids convTstring write barrier1264		print("\n")1265	})12661267	fatalthrow(throwTypeUser)1268	printunlock()1269}12701271// printPreFatalDeferPanic prints the panic1272// when fatal occurs in panics while running defer.1273func printPreFatalDeferPanic(p *_panic) {1274	// Don`t call preprintpanics, because1275	// don't want to call String/Error on the panicked values.1276	// When we fatal we really want to just print and exit,1277	// no more executing user Go code.1278	for x := p; x != nil; x = x.link {1279		if x.link != nil && *efaceOf(&x.link.arg) == *efaceOf(&x.arg) {1280			// This panic contains the same value as the next one in the chain.1281			// Mark it as repanicked. We will skip printing it twice in a row.1282			x.link.repanicked = true1283		}1284	}1285	if p != nil {1286		printpanics(p)1287		// make fatal have the same indentation as non-first panics.1288		print("\t")1289	}1290}12911292// runningPanicDefers is non-zero while running deferred functions for panic.1293// This is used to try hard to get a panic stack trace out when exiting.1294var runningPanicDefers atomic.Uint3212951296// panicking is non-zero when crashing the program for an unrecovered panic.1297var panicking atomic.Uint3212981299// paniclk is held while printing the panic information and stack trace,1300// so that two concurrent panics don't overlap their output.1301var paniclk mutex13021303// Unwind the stack after a deferred function calls recover1304// after a panic. Then arrange to continue running as though1305// the caller of the deferred function returned normally.1306//1307// However, if unwinding the stack would skip over a Goexit call, we1308// return into the Goexit loop instead, so it can continue processing1309// defers instead.1310func recovery(gp *g) {1311	p := gp._panic1312	pc, sp, fp := p.retpc, uintptr(p.sp), uintptr(p.fp)1313	p0, saveOpenDeferState := p, p.deferBitsPtr != nil && *p.deferBitsPtr != 013141315	// The linker records the f-relative address of a call to deferreturn in f's funcInfo.1316	// Assuming a "normal" call to recover() inside one of f's deferred functions1317	// invoked for a panic, that is the desired PC for exiting f.1318	f := findfunc(pc)1319	if f.deferreturn == 0 {1320		throw("no deferreturn")1321	}1322	gotoPc := f.entry() + uintptr(f.deferreturn)13231324	// Unwind the panic stack.1325	for ; p != nil && uintptr(p.startSP) < sp; p = p.link {1326		// Don't allow jumping past a pending Goexit.1327		// Instead, have its _panic.start() call return again.1328		//1329		// TODO(mdempsky): In this case, Goexit will resume walking the1330		// stack where it left off, which means it will need to rewalk1331		// frames that we've already processed.1332		//1333		// There's a similar issue with nested panics, when the inner1334		// panic supersedes the outer panic. Again, we end up needing to1335		// walk the same stack frames.1336		//1337		// These are probably pretty rare occurrences in practice, and1338		// they don't seem any worse than the existing logic. But if we1339		// move the unwinding state into _panic, we could detect when we1340		// run into where the last panic started, and then just pick up1341		// where it left off instead.1342		//1343		// With how subtle defer handling is, this might not actually be1344		// worthwhile though.1345		if p.goexit {1346			gotoPc, sp = p.startPC, uintptr(p.startSP)1347			saveOpenDeferState = false // goexit is unwinding the stack anyway1348			break1349		}13501351		runningPanicDefers.Add(-1)1352	}1353	gp._panic = p13541355	if p == nil { // must be done with signal1356		gp.sig = 01357	}13581359	if gp.param != nil {1360		throw("unexpected gp.param")1361	}1362	if saveOpenDeferState {1363		// If we're returning to deferreturn and there are more open-coded1364		// defers for it to call, save enough state for it to be able to1365		// pick up where p0 left off.1366		gp.param = unsafe.Pointer(&savedOpenDeferState{1367			retpc: p0.retpc,13681369			// We need to save deferBitsPtr and slotsPtr too, but those are1370			// stack pointers. To avoid issues around heap objects pointing1371			// to the stack, save them as offsets from SP.1372			deferBitsOffset: uintptr(unsafe.Pointer(p0.deferBitsPtr)) - uintptr(p0.sp),1373			slotsOffset:     uintptr(p0.slotsPtr) - uintptr(p0.sp),1374		})1375	}13761377	// TODO(mdempsky): Currently, we rely on frames containing "defer"1378	// to end with "CALL deferreturn; RET". This allows deferreturn to1379	// finish running any pending defers in the frame.1380	//1381	// But we should be able to tell whether there are still pending1382	// defers here. If there aren't, we can just jump directly to the1383	// "RET" instruction. And if there are, we don't need an actual1384	// "CALL deferreturn" instruction; we can simulate it with something1385	// like:1386	//1387	//	if usesLR {1388	//		lr = pc1389	//	} else {1390	//		sp -= sizeof(pc)1391	//		*(*uintptr)(sp) = pc1392	//	}1393	//	pc = funcPC(deferreturn)1394	//1395	// So that we effectively tail call into deferreturn, such that it1396	// then returns to the simple "RET" epilogue. That would save the1397	// overhead of the "deferreturn" call when there aren't actually any1398	// pending defers left, and shrink the TEXT size of compiled1399	// binaries. (Admittedly, both of these are modest savings.)14001401	// Ensure we're recovering within the appropriate stack.1402	if sp != 0 && (sp < gp.stack.lo || gp.stack.hi < sp) {1403		print("recover: ", hex(sp), " not in [", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n")1404		throw("bad recovery")1405	}14061407	// branch directly to the deferreturn1408	gp.sched.sp = sp1409	gp.sched.pc = gotoPc1410	gp.sched.lr = 01411	// Restore the bp on platforms that support frame pointers.1412	// N.B. It's fine to not set anything for platforms that don't1413	// support frame pointers, since nothing consumes them.1414	switch {1415	case goarch.IsAmd64 != 0:1416		// on x86, fp actually points one word higher than the top of1417		// the frame since the return address is saved on the stack by1418		// the caller1419		gp.sched.bp = fp - 2*goarch.PtrSize1420	case goarch.IsArm64 != 0:1421		// on arm64, the architectural bp points one word higher1422		// than the sp. fp is totally useless to us here, because it1423		// only gets us to the caller's fp.1424		gp.sched.bp = sp - goarch.PtrSize1425	}1426	gogo(&gp.sched)1427}14281429// fatalthrow implements an unrecoverable runtime throw. It freezes the1430// system, prints stack traces starting from its caller, and terminates the1431// process.1432//1433//go:nosplit1434func fatalthrow(t throwType) {1435	pc := sys.GetCallerPC()1436	sp := sys.GetCallerSP()1437	gp := getg()14381439	if gp.m.throwing == throwTypeNone {1440		gp.m.throwing = t1441	}14421443	// Switch to the system stack to avoid any stack growth, which may make1444	// things worse if the runtime is in a bad state.1445	systemstack(func() {1446		if isSecureMode() {1447			exit(2)1448		}14491450		startpanic_m()14511452		if dopanic_m(gp, pc, sp, nil) {1453			// crash uses a decent amount of nosplit stack and we're already1454			// low on stack in throw, so crash on the system stack (unlike1455			// fatalpanic).1456			crash()1457		}14581459		exit(2)1460	})14611462	*(*int)(nil) = 0 // not reached1463}14641465// fatalpanic implements an unrecoverable panic. It is like fatalthrow, except1466// that if msgs != nil, fatalpanic also prints panic messages and decrements1467// runningPanicDefers once main is blocked from exiting.1468//1469//go:nosplit1470func fatalpanic(msgs *_panic) {1471	pc := sys.GetCallerPC()1472	sp := sys.GetCallerSP()1473	gp := getg()1474	var docrash bool1475	// Switch to the system stack to avoid any stack growth, which1476	// may make things worse if the runtime is in a bad state.1477	systemstack(func() {1478		if startpanic_m() && msgs != nil {1479			// There were panic messages and startpanic_m1480			// says it's okay to try to print them.14811482			// startpanic_m set panicking, which will1483			// block main from exiting, so now OK to1484			// decrement runningPanicDefers.1485			runningPanicDefers.Add(-1)14861487			printpanics(msgs)1488		}14891490		// If this panic is the result of a synctest bubble deadlock,1491		// print stacks for the goroutines in the bubble.1492		var bubble *synctestBubble1493		if de, ok := msgs.arg.(synctestDeadlockError); ok {1494			bubble = de.bubble1495		}14961497		docrash = dopanic_m(gp, pc, sp, bubble)1498	})14991500	if docrash {1501		// By crashing outside the above systemstack call, debuggers1502		// will not be confused when generating a backtrace.1503		// Function crash is marked nosplit to avoid stack growth.1504		crash()1505	}15061507	systemstack(func() {1508		exit(2)1509	})15101511	*(*int)(nil) = 0 // not reached1512}15131514// startpanic_m prepares for an unrecoverable panic.1515//1516// It returns true if panic messages should be printed, or false if1517// the runtime is in bad shape and should just print stacks.1518//1519// It must not have write barriers even though the write barrier1520// explicitly ignores writes once dying > 0. Write barriers still1521// assume that g.m.p != nil, and this function may not have P1522// in some contexts (e.g. a panic in a signal handler for a signal1523// sent to an M with no P).1524//1525//go:nowritebarrierrec1526func startpanic_m() bool {1527	gp := getg()1528	if mheap_.cachealloc.size == 0 { // very early1529		print("runtime: panic before malloc heap initialized\n")1530	}1531	// Disallow malloc during an unrecoverable panic. A panic1532	// could happen in a signal handler, or in a throw, or inside1533	// malloc itself. We want to catch if an allocation ever does1534	// happen (even if we're not in one of these situations).1535	gp.m.mallocing++15361537	// If we're dying because of a bad lock count, set it to a1538	// good lock count so we don't recursively panic below.1539	if gp.m.locks < 0 {1540		gp.m.locks = 11541	}15421543	switch gp.m.dying {1544	case 0:1545		// Setting dying >0 has the side-effect of disabling this G's writebuf.1546		gp.m.dying = 11547		panicking.Add(1)1548		lock(&paniclk)1549		if debug.schedtrace > 0 || debug.scheddetail > 0 {1550			schedtrace(true)1551		}1552		freezetheworld()1553		return true1554	case 1:1555		// Something failed while panicking.1556		// Just print a stack trace and exit.1557		gp.m.dying = 21558		print("panic during panic\n")1559		return false1560	case 2:1561		// This is a genuine bug in the runtime, we couldn't even1562		// print the stack trace successfully.1563		gp.m.dying = 31564		print("stack trace unavailable\n")1565		exit(4)1566		fallthrough1567	default:1568		// Can't even print! Just exit.1569		exit(5)1570		return false // Need to return something.1571	}1572}15731574var didothers bool1575var deadlock mutex15761577// gp is the crashing g running on this M, but may be a user G, while getg() is1578// always g0.1579// If bubble is non-nil, print the stacks for goroutines in this group as well.1580func dopanic_m(gp *g, pc, sp uintptr, bubble *synctestBubble) bool {1581	if gp.sig != 0 {1582		signame := signame(gp.sig)1583		if signame != "" {1584			print("[signal ", signame)1585		} else {1586			print("[signal ", hex(gp.sig))1587		}1588		print(" code=", hex(gp.sigcode0), " addr=", hex(gp.sigcode1), " pc=", hex(gp.sigpc), "]\n")1589	}15901591	level, all, docrash := gotraceback()1592	if level > 0 {1593		if gp != gp.m.curg {1594			all = true1595		}1596		if gp != gp.m.g0 {1597			print("\n")1598			goroutineheader(gp)1599			traceback(pc, sp, 0, gp)1600		} else if level >= 2 || gp.m.throwing >= throwTypeRuntime {1601			print("\nruntime stack:\n")1602			traceback(pc, sp, 0, gp)1603		}1604		if !didothers {1605			if all {1606				didothers = true1607				tracebackothers(gp)1608			} else if bubble != nil {1609				// This panic is caused by a synctest bubble deadlock.1610				// Print stacks for goroutines in the deadlocked bubble.1611				tracebacksomeothers(gp, func(other *g) bool {1612					return bubble == other.bubble1613				})1614			}1615		}16161617	}1618	unlock(&paniclk)16191620	if panicking.Add(-1) != 0 {1621		// Some other m is panicking too.1622		// Let it print what it needs to print.1623		// Wait forever without chewing up cpu.1624		// It will exit when it's done.1625		lock(&deadlock)1626		lock(&deadlock)1627	}16281629	printDebugLog()16301631	return docrash1632}16331634// canpanic returns false if a signal should throw instead of1635// panicking.1636//1637//go:nosplit1638func canpanic() bool {1639	gp := getg()1640	mp := acquirem()16411642	// Is it okay for gp to panic instead of crashing the program?1643	// Yes, as long as it is running Go code, not runtime code,1644	// and not stuck in a system call.1645	if gp != mp.curg {1646		releasem(mp)1647		return false1648	}1649	// N.B. mp.locks != 1 instead of 0 to account for acquirem.1650	if mp.locks != 1 || mp.mallocing != 0 || mp.throwing != throwTypeNone || mp.preemptoff != "" || mp.dying != 0 {1651		releasem(mp)1652		return false1653	}1654	status := readgstatus(gp)1655	if status&^_Gscan != _Grunning || gp.syscallsp != 0 {1656		releasem(mp)1657		return false1658	}1659	if GOOS == "windows" && mp.libcallsp != 0 {1660		releasem(mp)1661		return false1662	}1663	releasem(mp)1664	return true1665}16661667// shouldPushSigpanic reports whether pc should be used as sigpanic's1668// return PC (pushing a frame for the call). Otherwise, it should be1669// left alone so that LR is used as sigpanic's return PC, effectively1670// replacing the top-most frame with sigpanic. This is used by1671// preparePanic.1672func shouldPushSigpanic(gp *g, pc, lr uintptr) bool {1673	if pc == 0 {1674		// Probably a call to a nil func. The old LR is more1675		// useful in the stack trace. Not pushing the frame1676		// will make the trace look like a call to sigpanic1677		// instead. (Otherwise the trace will end at sigpanic1678		// and we won't get to see who faulted.)1679		return false1680	}1681	// If we don't recognize the PC as code, but we do recognize1682	// the link register as code, then this assumes the panic was1683	// caused by a call to non-code. In this case, we want to1684	// ignore this call to make unwinding show the context.1685	//1686	// If we running C code, we're not going to recognize pc as a1687	// Go function, so just assume it's good. Otherwise, traceback1688	// may try to read a stale LR that looks like a Go code1689	// pointer and wander into the woods.1690	if gp.m.incgo || findfunc(pc).valid() {1691		// This wasn't a bad call, so use PC as sigpanic's1692		// return PC.1693		return true1694	}1695	if findfunc(lr).valid() {1696		// This was a bad call, but the LR is good, so use the1697		// LR as sigpanic's return PC.1698		return false1699	}1700	// Neither the PC or LR is good. Hopefully pushing a frame1701	// will work.1702	return true1703}17041705// isAbortPC reports whether pc is the program counter at which1706// runtime.abort raises a signal.1707//1708// It is nosplit because it's part of the isgoexception1709// implementation.1710//1711//go:nosplit1712func isAbortPC(pc uintptr) bool {1713	f := findfunc(pc)1714	if !f.valid() {1715		return false1716	}1717	return f.funcID == abi.FuncID_abort1718}17191720// For debugging only.1721//1722//go:noinline1723//go:nosplit1724func dumpPanicDeferState(where string, gp *g) {1725	systemstack(func() {1726		println("DUMPPANICDEFERSTATE", where)1727		p := gp._panic1728		d := gp._defer1729		var u unwinder1730		for u.init(gp, 0); u.valid(); u.next() {1731			// Print frame.1732			println("  frame sp=", hex(u.frame.sp), "fp=", hex(u.frame.fp), "pc=", pcName(u.frame.pc), "+", pcOff(u.frame.pc))1733			// Print panic.1734			for p != nil && uintptr(p.sp) == u.frame.sp {1735				println("    panic", p, "sp=", p.sp, "fp=", p.fp, "arg=", p.arg, "recovered=", p.recovered, "pc=", pcName(p.pc), "+", pcOff(p.pc), "retpc=", pcName(p.retpc), "+", pcOff(p.retpc), "startsp=", p.startSP, "startPC=", hex(p.startPC), pcName(p.startPC), "+", pcOff(p.startPC))1736				p = p.link1737			}17381739			// Print linked defers.1740			for d != nil && d.sp == u.frame.sp {1741				println("    defer(link)", "heap=", d.heap, "rangefunc=", d.rangefunc, fnName(d.fn))1742				d = d.link1743			}17441745			// Print open-coded defers.1746			// (A function is all linked or all open-coded, so we don't1747			// need to interleave this loop with the one above.)1748			fd := funcdata(u.frame.fn, abi.FUNCDATA_OpenCodedDeferInfo)1749			if fd != nil {1750				deferBitsOffset, fd := readvarintUnsafe(fd)1751				m := *(*uint8)(unsafe.Pointer(u.frame.varp - uintptr(deferBitsOffset)))1752				slotsOffset, fd := readvarintUnsafe(fd)1753				slots := u.frame.varp - uintptr(slotsOffset)1754				for i := 7; i >= 0; i-- {1755					if m>>i&1 == 0 {1756						continue1757					}1758					fn := *(*func())(unsafe.Pointer(slots + uintptr(i)*goarch.PtrSize))1759					println("    defer(open)", fnName(fn))1760				}1761			}17621763		}1764		if p != nil {1765			println("  REMAINING PANICS!", p)1766		}1767		if d != nil {1768			println("  REMAINING DEFERS!")1769		}1770	})1771}17721773func pcName(pc uintptr) string {1774	fn := findfunc(pc)1775	if !fn.valid() {1776		return "<unk>"1777	}1778	return funcname(fn)1779}1780func pcOff(pc uintptr) hex {1781	fn := findfunc(pc)1782	if !fn.valid() {1783		return 01784	}1785	return hex(pc - fn.entry())1786}1787func fnName(fn func()) string {1788	return pcName(**(**uintptr)(unsafe.Pointer(&fn)))1789}

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.