aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/runtime/panic.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/runtime/panic.go')
-rw-r--r--libgo/go/runtime/panic.go170
1 files changed, 139 insertions, 31 deletions
diff --git a/libgo/go/runtime/panic.go b/libgo/go/runtime/panic.go
index 88c0a4d..5868430 100644
--- a/libgo/go/runtime/panic.go
+++ b/libgo/go/runtime/panic.go
@@ -23,81 +23,189 @@ import (
//go:linkname makefuncreturning runtime.makefuncreturning
//go:linkname gorecover runtime.gorecover
//go:linkname deferredrecover runtime.deferredrecover
+//go:linkname goPanicIndex runtime.goPanicIndex
+//go:linkname goPanicIndexU runtime.goPanicIndexU
+//go:linkname goPanicSliceAlen runtime.goPanicSliceAlen
+//go:linkname goPanicSliceAlenU runtime.goPanicSliceAlenU
+//go:linkname goPanicSliceAcap runtime.goPanicSliceAcap
+//go:linkname goPanicSliceAcapU runtime.goPanicSliceAcapU
+//go:linkname goPanicSliceB runtime.goPanicSliceB
+//go:linkname goPanicSliceBU runtime.goPanicSliceBU
+//go:linkname goPanicSlice3Alen runtime.goPanicSlice3Alen
+//go:linkname goPanicSlice3AlenU runtime.goPanicSlice3AlenU
+//go:linkname goPanicSlice3Acap runtime.goPanicSlice3Acap
+//go:linkname goPanicSlice3AcapU runtime.goPanicSlice3AcapU
+//go:linkname goPanicSlice3B runtime.goPanicSlice3B
+//go:linkname goPanicSlice3BU runtime.goPanicSlice3BU
+//go:linkname goPanicSlice3C runtime.goPanicSlice3C
+//go:linkname goPanicSlice3CU runtime.goPanicSlice3CU
//go:linkname panicmem runtime.panicmem
// Temporary for C code to call:
//go:linkname throw runtime.throw
-// Calling panic with one of the errors below will call errorString.Error
-// which will call mallocgc to concatenate strings. That will fail if
-// malloc is locked, causing a confusing error message. Throw a better
-// error message instead.
-func panicCheckMalloc(err error) {
+// 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) {
+ name, _, _, _ := funcfileline(pc-1, -1)
+ if hasPrefix(name, "runtime.") {
+ throw(msg)
+ }
+ // TODO: is this redundant? How could we be in malloc
+ // but not in the runtime? runtime/internal/*, maybe?
gp := getg()
if gp != nil && gp.m != nil && gp.m.mallocing != 0 {
- throw(string(err.(errorString)))
+ throw(msg)
}
}
-var indexError = error(errorString("index out of range"))
+// 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) {
+ // panic allocates, so to avoid recursive malloc, turn panics
+ // during malloc into throws.
+ gp := getg()
+ if gp != nil && gp.m != nil && gp.m.mallocing != 0 {
+ throw(err)
+ }
+}
-// The panicindex, panicslice, and panicdivide functions are called by
+// Many of the following panic entry-points turn into throws when they
+// happen in various runtime contexts. These should never happen in
+// the runtime, and if they do, they indicate a serious issue and
+// should not be caught by user code.
+//
+// The panic{Index,Slice,divide,shift} functions are called by
// code generated by the compiler for out of bounds index expressions,
-// out of bounds slice expressions, and division by zero. The
-// panicdivide (again), panicoverflow, panicfloat, and panicmem
+// out of bounds slice expressions, division by zero, and shift by negative.
+// The panicdivide (again), panicoverflow, panicfloat, and panicmem
// functions are called by the signal handler when a signal occurs
// indicating the respective problem.
//
-// Since panicindex and panicslice are never called directly, and
+// Since panic{Index,Slice,shift} are never called directly, and
// since the runtime package should never have an out of bounds slice
-// or array reference, if we see those functions called from the
+// or array reference or negative shift, if we see those functions called from the
// runtime package we turn the panic into a throw. That will dump the
// entire runtime stack for easier debugging.
+//
+// The entry points called by the signal handler will be called from
+// runtime.sigpanic, so we can't disallow calls from the runtime to
+// these (they always look like they're called from the runtime).
+// Hence, for these, we just check for clearly bad runtime conditions.
+
+// failures in the comparisons for s[x], 0 <= x < y (y == len(s))
+func goPanicIndex(x int, y int) {
+ panicCheck1(getcallerpc(), "index out of range")
+ panic(boundsError{x: int64(x), signed: true, y: y, code: boundsIndex})
+}
+func goPanicIndexU(x uint, y int) {
+ panicCheck1(getcallerpc(), "index out of range")
+ panic(boundsError{x: int64(x), signed: false, y: y, code: boundsIndex})
+}
-func panicindex() {
- name, _, _, _ := funcfileline(getcallerpc()-1, -1)
- if hasPrefix(name, "runtime.") {
- throw(string(indexError.(errorString)))
- }
- panicCheckMalloc(indexError)
- panic(indexError)
+// failures in the comparisons for s[:x], 0 <= x <= y (y == len(s) or cap(s))
+func goPanicSliceAlen(x int, y int) {
+ panicCheck1(getcallerpc(), "slice bounds out of range")
+ panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSliceAlen})
+}
+func goPanicSliceAlenU(x uint, y int) {
+ panicCheck1(getcallerpc(), "slice bounds out of range")
+ panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSliceAlen})
+}
+func goPanicSliceAcap(x int, y int) {
+ panicCheck1(getcallerpc(), "slice bounds out of range")
+ panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSliceAcap})
+}
+func goPanicSliceAcapU(x uint, y int) {
+ panicCheck1(getcallerpc(), "slice bounds out of range")
+ panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSliceAcap})
}
-var sliceError = error(errorString("slice bounds out of range"))
+// failures in the comparisons for s[x:y], 0 <= x <= y
+func goPanicSliceB(x int, y int) {
+ panicCheck1(getcallerpc(), "slice bounds out of range")
+ panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSliceB})
+}
+func goPanicSliceBU(x uint, y int) {
+ panicCheck1(getcallerpc(), "slice bounds out of range")
+ panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSliceB})
+}
-func panicslice() {
- name, _, _, _ := funcfileline(getcallerpc()-1, -1)
- if hasPrefix(name, "runtime.") {
- throw(string(sliceError.(errorString)))
- }
- panicCheckMalloc(sliceError)
- panic(sliceError)
+// failures in the comparisons for s[::x], 0 <= x <= y (y == len(s) or cap(s))
+func goPanicSlice3Alen(x int, y int) {
+ panicCheck1(getcallerpc(), "slice bounds out of range")
+ panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSlice3Alen})
+}
+func goPanicSlice3AlenU(x uint, y int) {
+ panicCheck1(getcallerpc(), "slice bounds out of range")
+ panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3Alen})
+}
+func goPanicSlice3Acap(x int, y int) {
+ panicCheck1(getcallerpc(), "slice bounds out of range")
+ panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSlice3Acap})
+}
+func goPanicSlice3AcapU(x uint, y int) {
+ panicCheck1(getcallerpc(), "slice bounds out of range")
+ panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3Acap})
+}
+
+// failures in the comparisons for s[:x:y], 0 <= x <= y
+func goPanicSlice3B(x int, y int) {
+ panicCheck1(getcallerpc(), "slice bounds out of range")
+ panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSlice3B})
+}
+func goPanicSlice3BU(x uint, y int) {
+ panicCheck1(getcallerpc(), "slice bounds out of range")
+ panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3B})
+}
+
+// failures in the comparisons for s[x:y:], 0 <= x <= y
+func goPanicSlice3C(x int, y int) {
+ panicCheck1(getcallerpc(), "slice bounds out of range")
+ panic(boundsError{x: int64(x), signed: true, y: y, code: boundsSlice3C})
+}
+func goPanicSlice3CU(x uint, y int) {
+ panicCheck1(getcallerpc(), "slice bounds out of range")
+ panic(boundsError{x: int64(x), signed: false, y: y, code: boundsSlice3C})
+}
+
+var shiftError = error(errorString("negative shift amount"))
+
+func panicshift() {
+ panicCheck1(getcallerpc(), "negative shift amount")
+ panic(shiftError)
}
var divideError = error(errorString("integer divide by zero"))
func panicdivide() {
- panicCheckMalloc(divideError)
+ panicCheck2("integer divide by zero")
panic(divideError)
}
var overflowError = error(errorString("integer overflow"))
func panicoverflow() {
- panicCheckMalloc(overflowError)
+ panicCheck2("integer overflow")
panic(overflowError)
}
var floatError = error(errorString("floating point error"))
func panicfloat() {
- panicCheckMalloc(floatError)
+ panicCheck2("floating point error")
panic(floatError)
}
var memoryError = error(errorString("invalid memory address or nil pointer dereference"))
func panicmem() {
- panicCheckMalloc(memoryError)
+ panicCheck2("invalid memory address or nil pointer dereference")
panic(memoryError)
}