diff options
| author | Russ Cox <rsc@golang.org> | 2014-08-28 10:46:59 -0400 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2014-08-28 10:46:59 -0400 |
| commit | 6179aca54825867db3ab15bfff28fbda73e49378 (patch) | |
| tree | ed3dc9d0aa018e90985d6ad7483ed974aa7394cf /src/pkg/runtime/extern.go | |
| parent | b53b47f5ac9e11fdcd3f704bc2cb0828bdee6958 (diff) | |
| download | go-6179aca54825867db3ab15bfff28fbda73e49378.tar.xz | |
runtime: convert runtime1.goc, noasm_arm.goc to Go
LGTM=dvyukov
R=golang-codereviews, bradfitz, dvyukov
CC=golang-codereviews, iant, khr
https://golang.org/cl/135070043
Diffstat (limited to 'src/pkg/runtime/extern.go')
| -rw-r--r-- | src/pkg/runtime/extern.go | 69 |
1 files changed, 66 insertions, 3 deletions
diff --git a/src/pkg/runtime/extern.go b/src/pkg/runtime/extern.go index 1a2d9c21a2..0e48bb9d88 100644 --- a/src/pkg/runtime/extern.go +++ b/src/pkg/runtime/extern.go @@ -75,6 +75,8 @@ of the run-time system. */ package runtime +import "unsafe" + // Goexit terminates the goroutine that calls it. No other goroutine is affected. // Goexit runs all deferred calls before terminating the goroutine. // @@ -84,28 +86,89 @@ package runtime // If all other goroutines exit, the program crashes. func Goexit() +// We assume that all architectures turn faults and the like +// into apparent calls to runtime.sigpanic. If we see a "call" +// to runtime.sigpanic, we do not back up the PC to find the +// line number of the CALL instruction, because there is no CALL. +var sigpanic byte + // Caller reports file and line number information about function invocations on // the calling goroutine's stack. The argument skip is the number of stack frames // to ascend, with 0 identifying the caller of Caller. (For historical reasons the // meaning of skip differs between Caller and Callers.) The return values report the // program counter, file name, and line number within the file of the corresponding // call. The boolean ok is false if it was not possible to recover the information. -func Caller(skip int) (pc uintptr, file string, line int, ok bool) +func Caller(skip int) (pc uintptr, file string, line int, ok bool) { + // Ask for two PCs: the one we were asked for + // and what it called, so that we can see if it + // "called" sigpanic. + var rpc [2]uintptr + if callers(int32(1+skip-1), &rpc[0], 2) < 2 { + return + } + f := findfunc(rpc[1]) + if f == nil { + // TODO(rsc): Probably a bug? + // The C version said "have retpc at least" + // but actually returned pc=0. + ok = true + return + } + pc = rpc[1] + xpc := pc + g := findfunc(rpc[0]) + if xpc > f.entry && (g == nil || g.entry != uintptr(unsafe.Pointer(&sigpanic))) { + xpc-- + } + line = int(funcline(f, xpc, &file)) + ok = true + return +} + +func findfunc(uintptr) *_func + +//go:noescape +func funcline(*_func, uintptr, *string) int32 // Callers fills the slice pc with the program counters of function invocations // on the calling goroutine's stack. The argument skip is the number of stack frames // to skip before recording in pc, with 0 identifying the frame for Callers itself and // 1 identifying the caller of Callers. // It returns the number of entries written to pc. -func Callers(skip int, pc []uintptr) int +func Callers(skip int, pc []uintptr) int { + // runtime.callers uses pc.array==nil as a signal + // to print a stack trace. Pick off 0-length pc here + // so that we don't let a nil pc slice get to it. + if len(pc) == 0 { + return 0 + } + return int(callers(int32(skip), &pc[0], int32(len(pc)))) +} + +//go:noescape +func callers(int32, *uintptr, int32) int32 func getgoroot() string +func environ() []string + +func gogetenv(key string) string { + env := environ() + if env == nil { + gothrow("getenv before env init") + } + for _, s := range env { + if len(s) > len(key) && s[len(key)] == '=' && s[:len(key)] == key { + return s[len(key)+1:] + } + } + return "" +} // GOROOT returns the root of the Go tree. // It uses the GOROOT environment variable, if set, // or else the root used during the Go build. func GOROOT() string { - s := getgoroot() + s := gogetenv("GOROOT") if s != "" { return s } |
