diff options
author | Russ Cox <rsc@golang.org> | 2013-02-15 14:27:16 -0500 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2013-02-15 14:27:16 -0500 |
commit | 095f80182deb851e1518b31d742ee8a267e6d6c3 (patch) | |
tree | c44e31815cf3faca2f7248595343f7af2be05244 | |
parent | 5c398dfc0a24bac9b6da6b50909f587d0e068ad1 (diff) | |
download | go-095f80182deb851e1518b31d742ee8a267e6d6c3.tar.gz |
runtime/pprof: adjust reported line numbers to show call sites
This is the same logic used in the standard tracebacks.
The caller pc is the pc after the call, so except in the
fake "call" caused by a panic, back up the pc enough
that the lookup will use the previous instruction.
Fixes issue 4150.
Fixes issue 4151.
R=golang-dev, iant
CC=golang-dev
https://codereview.appspot.com/7317047
-rw-r--r-- | src/pkg/runtime/pprof/pprof.go | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/src/pkg/runtime/pprof/pprof.go b/src/pkg/runtime/pprof/pprof.go index ee81c94a2..32c1098b9 100644 --- a/src/pkg/runtime/pprof/pprof.go +++ b/src/pkg/runtime/pprof/pprof.go @@ -318,21 +318,33 @@ func printCountProfile(w io.Writer, debug int, name string, p countProfile) erro // for a single stack trace. func printStackRecord(w io.Writer, stk []uintptr, allFrames bool) { show := allFrames - for _, pc := range stk { + wasPanic := false + for i, pc := range stk { f := runtime.FuncForPC(pc) if f == nil { show = true fmt.Fprintf(w, "#\t%#x\n", pc) + wasPanic = false } else { - file, line := f.FileLine(pc) + tracepc := pc + // Back up to call instruction. + if i > 0 && pc > f.Entry() && !wasPanic { + if runtime.GOARCH == "386" || runtime.GOARCH == "amd64" { + tracepc-- + } else { + tracepc -= 4 // arm, etc + } + } + file, line := f.FileLine(tracepc) name := f.Name() // Hide runtime.goexit and any runtime functions at the beginning. // This is useful mainly for allocation traces. + wasPanic = name == "runtime.panic" if name == "runtime.goexit" || !show && strings.HasPrefix(name, "runtime.") { continue } show = true - fmt.Fprintf(w, "#\t%#x\t%s+%#x\t%s:%d\n", pc, f.Name(), pc-f.Entry(), file, line) + fmt.Fprintf(w, "#\t%#x\t%s+%#x\t%s:%d\n", pc, name, pc-f.Entry(), file, line) } } if !show { |