type throwType … const throwTypeNone … const throwTypeUser … const throwTypeRuntime … // Check to make sure we can really generate a panic. If the panic // was generated from the runtime, or from inside malloc, then convert // to a throw of msg. // pc should be the program counter of the compiler-generated code that // triggered this panic. func panicCheck1(pc uintptr, msg string) { … } // Same as above, but calling from the runtime is allowed. // // Using this function is necessary for any panic that may be // generated by runtime.sigpanic, since those are always called by the // runtime. func panicCheck2(err string) { … } // failures in the comparisons for s[x], 0 <= x < y (y == len(s)) // //go:yeswritebarrierrec func goPanicIndex(x int, y int) { … } //go:yeswritebarrierrec func goPanicIndexU(x uint, y int) { … } // failures in the comparisons for s[:x], 0 <= x <= y (y == len(s) or cap(s)) // //go:yeswritebarrierrec func goPanicSliceAlen(x int, y int) { … } //go:yeswritebarrierrec func goPanicSliceAlenU(x uint, y int) { … } //go:yeswritebarrierrec func goPanicSliceAcap(x int, y int) { … } //go:yeswritebarrierrec func goPanicSliceAcapU(x uint, y int) { … } // failures in the comparisons for s[x:y], 0 <= x <= y // //go:yeswritebarrierrec func goPanicSliceB(x int, y int) { … } //go:yeswritebarrierrec func goPanicSliceBU(x uint, y int) { … } // failures in the comparisons for s[::x], 0 <= x <= y (y == len(s) or cap(s)) func goPanicSlice3Alen(x int, y int) { … } func goPanicSlice3AlenU(x uint, y int) { … } func goPanicSlice3Acap(x int, y int) { … } func goPanicSlice3AcapU(x uint, y int) { … } // failures in the comparisons for s[:x:y], 0 <= x <= y func goPanicSlice3B(x int, y int) { … } func goPanicSlice3BU(x uint, y int) { … } // failures in the comparisons for s[x:y:], 0 <= x <= y func goPanicSlice3C(x int, y int) { … } func goPanicSlice3CU(x uint, y int) { … } // failures in the conversion ([x]T)(s) or (*[x]T)(s), 0 <= x <= y, y == len(s) func goPanicSliceConvert(x int, y int) { … } // Implemented in assembly, as they take arguments in registers. // Declared here to mark them as ABIInternal. func panicIndex(x int, y int) func panicIndexU(x uint, y int) func panicSliceAlen(x int, y int) func panicSliceAlenU(x uint, y int) func panicSliceAcap(x int, y int) func panicSliceAcapU(x uint, y int) func panicSliceB(x int, y int) func panicSliceBU(x uint, y int) func panicSlice3Alen(x int, y int) func panicSlice3AlenU(x uint, y int) func panicSlice3Acap(x int, y int) func panicSlice3AcapU(x uint, y int) func panicSlice3B(x int, y int) func panicSlice3BU(x uint, y int) func panicSlice3C(x int, y int) func panicSlice3CU(x uint, y int) func panicSliceConvert(x int, y int) var shiftError … //go:yeswritebarrierrec func panicshift() { … } var divideError … //go:yeswritebarrierrec func panicdivide() { … } var overflowError … func panicoverflow() { … } var floatError … func panicfloat() { … } var memoryError … func panicmem() { … } func panicmemAddr(addr uintptr) { … } // Create a new deferred function fn, which has no arguments and results. // The compiler turns a defer statement into a call to this. func deferproc(fn func()) { … } var rangeDoneError … var rangePanicError … var rangeExhaustedError … var rangeMissingPanicError … //go:noinline func panicrangestate(state int) { … } // deferrangefunc is called by functions that are about to // execute a range-over-function loop in which the loop body // may execute a defer statement. That defer needs to add to // the chain for the current function, not the func literal synthesized // to represent the loop body. To do that, the original function // calls deferrangefunc to obtain an opaque token representing // the current frame, and then the loop body uses deferprocat // instead of deferproc to add to that frame's defer lists. // // The token is an 'any' with underlying type *atomic.Pointer[_defer]. // It is the atomically-updated head of a linked list of _defer structs // representing deferred calls. At the same time, we create a _defer // struct on the main g._defer list with d.head set to this head pointer. // // The g._defer list is now a linked list of deferred calls, // but an atomic list hanging off: // // g._defer => d4 -> d3 -> drangefunc -> d2 -> d1 -> nil // | .head // | // +--> dY -> dX -> nil // // with each -> indicating a d.link pointer, and where drangefunc // has the d.rangefunc = true bit set. // Note that the function being ranged over may have added // its own defers (d4 and d3), so drangefunc need not be at the // top of the list when deferprocat is used. This is why we pass // the atomic head explicitly. // // To keep misbehaving programs from crashing the runtime, // deferprocat pushes new defers onto the .head list atomically. // The fact that it is a separate list from the main goroutine // defer list means that the main goroutine's defers can still // be handled non-atomically. // // In the diagram, dY and dX are meant to be processed when // drangefunc would be processed, which is to say the defer order // should be d4, d3, dY, dX, d2, d1. To make that happen, // when defer processing reaches a d with rangefunc=true, // it calls deferconvert to atomically take the extras // away from d.head and then adds them to the main list. // // That is, deferconvert changes this list: // // g._defer => drangefunc -> d2 -> d1 -> nil // | .head // | // +--> dY -> dX -> nil // // into this list: // // g._defer => dY -> dX -> d2 -> d1 -> nil // // It also poisons *drangefunc.head so that any future // deferprocat using that head will throw. // (The atomic head is ordinary garbage collected memory so that // it's not a problem if user code holds onto it beyond // the lifetime of drangefunc.) // // TODO: We could arrange for the compiler to call into the // runtime after the loop finishes normally, to do an eager // deferconvert, which would catch calling the loop body // and having it defer after the loop is done. If we have a // more general catch of loop body misuse, though, this // might not be worth worrying about in addition. // // See also ../cmd/compile/internal/rangefunc/rewrite.go. func deferrangefunc() any { … } // badDefer returns a fixed bad defer pointer for poisoning an atomic defer list head. func badDefer() *_defer { … } // deferprocat is like deferproc but adds to the atomic list represented by frame. // See the doc comment for deferrangefunc for details. func deferprocat(fn func(), frame any) { … } // deferconvert converts the rangefunc defer list of d0 into an ordinary list // following d0. // See the doc comment for deferrangefunc for details. func deferconvert(d0 *_defer) { … } // deferprocStack queues a new deferred function with a defer record on the stack. // The defer record must have its fn field initialized. // All other fields can contain junk. // Nosplit because of the uninitialized pointer fields on the stack. // //go:nosplit func deferprocStack(d *_defer) { … } // Allocate a Defer, usually using per-P pool. // Each defer must be released with freedefer. The defer is not // added to any defer chain yet. func newdefer() *_defer { … } // popDefer pops the head of gp's defer list and frees it. func popDefer(gp *g) { … } // deferreturn runs deferred functions for the caller's frame. // The compiler inserts a call to this at the end of any // function which calls defer. func deferreturn() { … } // Goexit terminates the goroutine that calls it. No other goroutine is affected. // Goexit runs all deferred calls before terminating the goroutine. Because Goexit // is not a panic, any recover calls in those deferred functions will return nil. // // Calling Goexit from the main goroutine terminates that goroutine // without func main returning. Since func main has not returned, // the program continues execution of other goroutines. // If all other goroutines exit, the program crashes. // // It crashes if called from a thread not created by the Go runtime. func Goexit() { … } // Call all Error and String methods before freezing the world. // Used when crashing with panicking. func preprintpanics(p *_panic) { … } // Print all currently active panics. Used when crashing. // Should only be called after preprintpanics. func printpanics(p *_panic) { … } // readvarintUnsafe reads the uint32 in varint format starting at fd, and returns the // uint32 and a pointer to the byte following the varint. // // The implementation is the same with runtime.readvarint, except that this function // uses unsafe.Pointer for speed. func readvarintUnsafe(fd unsafe.Pointer) (uint32, unsafe.Pointer) { … } type PanicNilError … func (*PanicNilError) Error() string { … } func (*PanicNilError) RuntimeError() { … } var panicnil … // The implementation of the predeclared function panic. // The compiler emits calls to this function. // // gopanic should be an internal detail, // but widely used packages access it using linkname. // Notable members of the hall of shame include: // - go.undefinedlabs.com/scopeagent // - github.com/goplus/igop // // Do not remove or change the type signature. // See go.dev/issue/67401. // //go:linkname gopanic func gopanic(e any) { … } // start initializes a panic to start unwinding the stack. // // If p.goexit is true, then start may return multiple times. func (p *_panic) start(pc uintptr, sp unsafe.Pointer) { … } // nextDefer returns the next deferred function to invoke, if any. // // Note: The "ok bool" result is necessary to correctly handle when // the deferred function itself was nil (e.g., "defer (func())(nil)"). func (p *_panic) nextDefer() (func(), bool) { … } // nextFrame finds the next frame that contains deferred calls, if any. func (p *_panic) nextFrame() (ok bool) { … } func (p *_panic) initOpenCodedDefers(fn funcInfo, varp unsafe.Pointer) bool { … } // The implementation of the predeclared function recover. // Cannot split the stack because it needs to reliably // find the stack segment of its caller. // // TODO(rsc): Once we commit to CopyStackAlways, // this doesn't need to be nosplit. // //go:nosplit func gorecover(argp uintptr) any { … } //go:linkname sync_throw sync.throw func sync_throw(s string) { … } //go:linkname sync_fatal sync.fatal func sync_fatal(s string) { … } //go:linkname rand_fatal crypto/rand.fatal func rand_fatal(s string) { … } //go:linkname fips_fatal crypto/internal/fips.fatal func fips_fatal(s string) { … } //go:linkname maps_fatal internal/runtime/maps.fatal func maps_fatal(s string) { … } // throw triggers a fatal error that dumps a stack trace and exits. // // throw should be used for runtime-internal fatal errors where Go itself, // rather than user code, may be at fault for the failure. // // NOTE: temporarily marked "go:noinline" pending investigation/fix of // issue #67274, so as to fix longtest builders. // // throw should be an internal detail, // but widely used packages access it using linkname. // Notable members of the hall of shame include: // - github.com/bytedance/sonic // - github.com/cockroachdb/pebble // - github.com/dgraph-io/ristretto // - github.com/outcaste-io/ristretto // - github.com/pingcap/br // - gvisor.dev/gvisor // - github.com/sagernet/gvisor // // Do not remove or change the type signature. // See go.dev/issue/67401. // //go:linkname throw //go:nosplit func throw(s string) { … } // fatal triggers a fatal error that dumps a stack trace and exits. // // fatal is equivalent to throw, but is used when user code is expected to be // at fault for the failure, such as racing map writes. // // fatal does not include runtime frames, system goroutines, or frame metadata // (fp, sp, pc) in the stack trace unless GOTRACEBACK=system or higher. // //go:nosplit func fatal(s string) { … } var runningPanicDefers … var panicking … var paniclk … // Unwind the stack after a deferred function calls recover // after a panic. Then arrange to continue running as though // the caller of the deferred function returned normally. // // However, if unwinding the stack would skip over a Goexit call, we // return into the Goexit loop instead, so it can continue processing // defers instead. func recovery(gp *g) { … } // fatalthrow implements an unrecoverable runtime throw. It freezes the // system, prints stack traces starting from its caller, and terminates the // process. // //go:nosplit func fatalthrow(t throwType) { … } // fatalpanic implements an unrecoverable panic. It is like fatalthrow, except // that if msgs != nil, fatalpanic also prints panic messages and decrements // runningPanicDefers once main is blocked from exiting. // //go:nosplit func fatalpanic(msgs *_panic) { … } // startpanic_m prepares for an unrecoverable panic. // // It returns true if panic messages should be printed, or false if // the runtime is in bad shape and should just print stacks. // // It must not have write barriers even though the write barrier // explicitly ignores writes once dying > 0. Write barriers still // assume that g.m.p != nil, and this function may not have P // in some contexts (e.g. a panic in a signal handler for a signal // sent to an M with no P). // //go:nowritebarrierrec func startpanic_m() bool { … } var didothers … var deadlock … // gp is the crashing g running on this M, but may be a user G, while getg() is // always g0. func dopanic_m(gp *g, pc, sp uintptr) bool { … } // canpanic returns false if a signal should throw instead of // panicking. // //go:nosplit func canpanic() bool { … } // shouldPushSigpanic reports whether pc should be used as sigpanic's // return PC (pushing a frame for the call). Otherwise, it should be // left alone so that LR is used as sigpanic's return PC, effectively // replacing the top-most frame with sigpanic. This is used by // preparePanic. func shouldPushSigpanic(gp *g, pc, lr uintptr) bool { … } // isAbortPC reports whether pc is the program counter at which // runtime.abort raises a signal. // // It is nosplit because it's part of the isgoexception // implementation. // //go:nosplit func isAbortPC(pc uintptr) bool { … }