Skip to content

Commit 232c979

Browse files
committed
runtime: store incremented PC in result of runtime.Callers
In 1.11 we stored "return addresses" in the result of runtime.Callers. I changed that behavior in CL 152537 to store an address in the call instruction itself. This CL reverts that part of 152537. The change in 152537 was made because we now store pcs of inline marks in the result of runtime.Callers as well. This CL will now store the address of the inline mark + 1 in the results of runtime.Callers, so that the subsequent -1 done in CallersFrames will pick out the correct inline mark instruction. This CL means that the results of runtime.Callers can be passed to runtime.FuncForPC as they were before. There are a bunch of packages in the wild that take the results of runtime.Callers, subtract 1, and then call FuncForPC. This CL keeps that pattern working as it did in 1.11. The changes to runtime/pprof in this CL are exactly a revert of the changes to that package in 152537 (except the locForPC comment). Update #29582 Change-Id: I04d232000fb482f0f0ff6277f8d7b9c72e97eb48 Reviewed-on: https://go-review.googlesource.com/c/156657 Reviewed-by: Ian Lance Taylor <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent a1d5e8a commit 232c979

File tree

5 files changed

+31
-9
lines changed

5 files changed

+31
-9
lines changed

src/runtime/pprof/proto.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ func (b *profileBuilder) pbMapping(tag int, id, base, limit, offset uint64, file
208208
}
209209

210210
// locForPC returns the location ID for addr.
211-
// addr must a PC which is part of a call or the PC of an inline marker. This returns the location of the call.
211+
// addr must a return PC or 1 + the PC of an inline marker. This returns the location of the corresponding call.
212212
// It may emit to b.pb, so there must be no message encoding in progress.
213213
func (b *profileBuilder) locForPC(addr uintptr) uint64 {
214214
id := uint64(b.locs[addr])
@@ -236,7 +236,7 @@ func (b *profileBuilder) locForPC(addr uintptr) uint64 {
236236
if frame.PC == 0 {
237237
// If we failed to resolve the frame, at least make up
238238
// a reasonable call PC. This mostly happens in tests.
239-
frame.PC = addr
239+
frame.PC = addr - 1
240240
}
241241

242242
// We can't write out functions while in the middle of the
@@ -403,7 +403,16 @@ func (b *profileBuilder) build() {
403403
}
404404

405405
locs = locs[:0]
406-
for _, addr := range e.stk {
406+
for i, addr := range e.stk {
407+
// Addresses from stack traces point to the
408+
// next instruction after each call, except
409+
// for the leaf, which points to where the
410+
// signal occurred. locForPC expects return
411+
// PCs, so increment the leaf address to look
412+
// like a return PC.
413+
if i == 0 {
414+
addr++
415+
}
407416
l := b.locForPC(addr)
408417
if l == 0 { // runtime.goexit
409418
continue

src/runtime/pprof/proto_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,11 @@ func TestConvertCPUProfile(t *testing.T) {
133133
samples := []*profile.Sample{
134134
{Value: []int64{20, 20 * 2000 * 1000}, Location: []*profile.Location{
135135
{ID: 1, Mapping: map1, Address: addr1},
136-
{ID: 2, Mapping: map1, Address: addr1 + 2},
136+
{ID: 2, Mapping: map1, Address: addr1 + 1},
137137
}},
138138
{Value: []int64{40, 40 * 2000 * 1000}, Location: []*profile.Location{
139139
{ID: 3, Mapping: map2, Address: addr2},
140-
{ID: 4, Mapping: map2, Address: addr2 + 2},
140+
{ID: 4, Mapping: map2, Address: addr2 + 1},
141141
}},
142142
}
143143
checkProfile(t, p, period, periodType, sampleType, samples, "")

src/runtime/pprof/protomem_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ import (
1414
func TestConvertMemProfile(t *testing.T) {
1515
addr1, addr2, map1, map2 := testPCs(t)
1616

17-
a1, a2 := uintptr(addr1), uintptr(addr2)
17+
// MemProfileRecord stacks are return PCs, so add one to the
18+
// addresses recorded in the "profile". The proto profile
19+
// locations are call PCs, so conversion will subtract one
20+
// from these and get back to addr1 and addr2.
21+
a1, a2 := uintptr(addr1)+1, uintptr(addr2)+1
1822
rate := int64(512 * 1024)
1923
rec := []runtime.MemProfileRecord{
2024
{AllocBytes: 4096, FreeBytes: 1024, AllocObjects: 4, FreeObjects: 1, Stack0: [32]uintptr{a1, a2}},

src/runtime/symtab.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,13 @@ func (ci *Frames) Next() (frame Frame, more bool) {
8787
}
8888
f := funcInfo._Func()
8989
entry := f.Entry()
90+
if pc > entry {
91+
// We store the pc of the start of the instruction following
92+
// the instruction in question (the call or the inline mark).
93+
// This is done for historical reasons, and to make FuncForPC
94+
// work correctly for entries in the result of runtime.Callers.
95+
pc--
96+
}
9097
name := funcname(funcInfo)
9198
file, line := funcline1(funcInfo, pc, false)
9299
if inldata := funcdata(funcInfo, _FUNCDATA_InlTree); inldata != nil {

src/runtime/traceback.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -344,8 +344,9 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
344344
}
345345

346346
if pcbuf != nil {
347+
pc := frame.pc
347348
// backup to CALL instruction to read inlining info (same logic as below)
348-
tracepc := frame.pc
349+
tracepc := pc
349350
if (n > 0 || flags&_TraceTrap == 0) && frame.pc > f.entry && !waspanic {
350351
tracepc--
351352
}
@@ -363,12 +364,13 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
363364
} else if skip > 0 {
364365
skip--
365366
} else if n < max {
366-
(*[1 << 20]uintptr)(unsafe.Pointer(pcbuf))[n] = tracepc
367+
(*[1 << 20]uintptr)(unsafe.Pointer(pcbuf))[n] = pc
367368
n++
368369
}
369370
lastFuncID = inltree[ix].funcID
370371
// Back up to an instruction in the "caller".
371372
tracepc = frame.fn.entry + uintptr(inltree[ix].parentPc)
373+
pc = tracepc + 1
372374
}
373375
}
374376
// Record the main frame.
@@ -377,7 +379,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
377379
} else if skip > 0 {
378380
skip--
379381
} else if n < max {
380-
(*[1 << 20]uintptr)(unsafe.Pointer(pcbuf))[n] = tracepc
382+
(*[1 << 20]uintptr)(unsafe.Pointer(pcbuf))[n] = pc
381383
n++
382384
}
383385
lastFuncID = f.funcID

0 commit comments

Comments
 (0)