aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKeith Randall <khr@google.com>2019-09-23 14:36:48 -0700
committerKeith Randall <khr@golang.org>2019-11-08 21:05:17 +0000
commit9ee6ba089dc9dd2402bccd9ed28b07140f76de15 (patch)
tree49f74474a7613c22e062d96cd3d33b21eb4a4380 /src
parent9e914f55dded9f779aae86cfb2e989bc9a1d3ea4 (diff)
downloadgo-9ee6ba089dc9dd2402bccd9ed28b07140f76de15.tar.xz
runtime: fix line number for faulting instructions
Unlike function calls, when processing instructions that directly fault we must not subtract 1 from the pc before looking up the file/line information. Since the file/line lookup unconditionally subtracts 1, add 1 to the faulting instruction PCs to compensate. Fixes #34123 Change-Id: Ie7361e3d2f84a0d4f48d97e5a9e74f6291ba7a8b Reviewed-on: https://go-review.googlesource.com/c/go/+/196962 Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/runtime/pprof/proto.go6
-rw-r--r--src/runtime/pprof/proto_test.go6
-rw-r--r--src/runtime/traceback.go15
3 files changed, 17 insertions, 10 deletions
diff --git a/src/runtime/pprof/proto.go b/src/runtime/pprof/proto.go
index c269c3a652..3e6012df57 100644
--- a/src/runtime/pprof/proto.go
+++ b/src/runtime/pprof/proto.go
@@ -359,13 +359,7 @@ func (b *profileBuilder) build() {
}
}
- // Addresses from stack traces point to the next instruction after each call,
- // except for the leaf, which points to where the signal occurred.
- // appendLocsForStack expects return PCs so increment the leaf address to
- // look like a return PC.
- e.stk[0] += 1
locs = b.appendLocsForStack(locs[:0], e.stk)
- e.stk[0] -= 1 // undo the adjustment on the leaf.
b.pbSample(values, locs, labels)
}
diff --git a/src/runtime/pprof/proto_test.go b/src/runtime/pprof/proto_test.go
index eda2b003ad..f3456ffede 100644
--- a/src/runtime/pprof/proto_test.go
+++ b/src/runtime/pprof/proto_test.go
@@ -116,9 +116,9 @@ func TestConvertCPUProfile(t *testing.T) {
b := []uint64{
3, 0, 500, // hz = 500
- 5, 0, 10, uint64(addr1), uint64(addr1 + 2), // 10 samples in addr1
- 5, 0, 40, uint64(addr2), uint64(addr2 + 2), // 40 samples in addr2
- 5, 0, 10, uint64(addr1), uint64(addr1 + 2), // 10 samples in addr1
+ 5, 0, 10, uint64(addr1 + 1), uint64(addr1 + 2), // 10 samples in addr1
+ 5, 0, 40, uint64(addr2 + 1), uint64(addr2 + 2), // 40 samples in addr2
+ 5, 0, 10, uint64(addr1 + 1), uint64(addr1 + 2), // 10 samples in addr1
}
p, err := translateCPUProfile(b)
if err != nil {
diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go
index dc2a7a3693..944c8473d2 100644
--- a/src/runtime/traceback.go
+++ b/src/runtime/traceback.go
@@ -340,7 +340,20 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
pc := frame.pc
// backup to CALL instruction to read inlining info (same logic as below)
tracepc := pc
- if (n > 0 || flags&_TraceTrap == 0) && frame.pc > f.entry && !waspanic {
+ // Normally, pc is a return address. In that case, we want to look up
+ // file/line information using pc-1, because that is the pc of the
+ // call instruction (more precisely, the last byte of the call instruction).
+ // Callers expect the pc buffer to contain return addresses and do the
+ // same -1 themselves, so we keep pc unchanged.
+ // When the pc is from a signal (e.g. profiler or segv) then we want
+ // to look up file/line information using pc, and we store pc+1 in the
+ // pc buffer so callers can unconditionally subtract 1 before looking up.
+ // See issue 34123.
+ // The pc can be at function entry when the frame is initialized without
+ // actually running code, like runtime.mstart.
+ if (n == 0 && flags&_TraceTrap != 0) || waspanic || pc == f.entry {
+ pc++
+ } else {
tracepc--
}