diff options
Diffstat (limited to 'src/runtime/error.go')
| -rw-r--r-- | src/runtime/error.go | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/src/runtime/error.go b/src/runtime/error.go index 0238c5e592..f5b015c091 100644 --- a/src/runtime/error.go +++ b/src/runtime/error.go @@ -4,6 +4,8 @@ package runtime +import _ "unsafe" // for go:linkname + // The Error interface identifies a run time error. type Error interface { error @@ -91,7 +93,41 @@ func printany(i interface{}) { } } +// strings.IndexByte is implemented in runtime/asm_$goarch.s +// but amusingly we need go:linkname to get access to it here in the runtime. +//go:linkname stringsIndexByte strings.IndexByte +func stringsIndexByte(s string, c byte) int + // called from generated code -func panicwrap(pkg, typ, meth string) { +func panicwrap() { + pc := make([]uintptr, 1) + n := Callers(2, pc) + if n == 0 { + throw("panicwrap: Callers failed") + } + frames := CallersFrames(pc) + frame, _ := frames.Next() + name := frame.Function + // name is something like "main.(*T).F". + // We want to extract pkg ("main"), typ ("T"), and meth ("F"). + // Do it by finding the parens. + i := stringsIndexByte(name, '(') + if i < 0 { + throw("panicwrap: no ( in " + frame.Function) + } + pkg := name[:i-1] + if i+2 >= len(name) || name[i-1:i+2] != ".(*" { + throw("panicwrap: unexpected string after package name: " + frame.Function) + } + name = name[i+2:] + i = stringsIndexByte(name, ')') + if i < 0 { + throw("panicwrap: no ) in " + frame.Function) + } + if i+2 >= len(name) || name[i:i+2] != ")." { + throw("panicwrap: unexpected string after type name: " + frame.Function) + } + typ := name[:i] + meth := name[i+2:] panic(plainError("value method " + pkg + "." + typ + "." + meth + " called using nil *" + typ + " pointer")) } |
