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.