mirror of
https://github.com/golang/go
synced 2024-11-18 14:24:44 -07:00
runtime: use inlining tables to generate accurate tracebacks
The code in https://play.golang.org/p/aYQPrTtzoK now produces the following stack trace: goroutine 1 [running]: main.(*point).negate(...) /tmp/go/main.go:8 main.main() /tmp/go/main.go:14 +0x23 Previously the stack trace missed the inlined call: goroutine 1 [running]: main.main() /tmp/go/main.go:14 +0x23 Fixes #10152. Updates #19348. Change-Id: Ib43c67012f53da0ef1a1e69bcafb65b57d9cecb2 Reviewed-on: https://go-review.googlesource.com/37233 Run-TryBot: David Lazar <lazard@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com>
This commit is contained in:
parent
1c6ef9aeed
commit
781fd3998e
@ -538,3 +538,31 @@ func TestConcurrentMapIterateWrite(t *testing.T) {
|
||||
t.Fatalf("output does not start with %q:\n%s", want, output)
|
||||
}
|
||||
}
|
||||
|
||||
type point struct {
|
||||
x, y *int
|
||||
}
|
||||
|
||||
func (p *point) negate() {
|
||||
*p.x = *p.x * -1
|
||||
*p.y = *p.y * -1
|
||||
}
|
||||
|
||||
// Test for issue #10152.
|
||||
func TestPanicInlined(t *testing.T) {
|
||||
defer func() {
|
||||
r := recover()
|
||||
if r == nil {
|
||||
t.Fatalf("recover failed")
|
||||
}
|
||||
buf := make([]byte, 2048)
|
||||
n := runtime.Stack(buf, false)
|
||||
buf = buf[:n]
|
||||
if !bytes.Contains(buf, []byte("(*point).negate(")) {
|
||||
t.Fatalf("expecting stack trace to contain call to (*point).negate()")
|
||||
}
|
||||
}()
|
||||
|
||||
pt := new(point)
|
||||
pt.negate()
|
||||
}
|
||||
|
@ -604,6 +604,23 @@ func funcname(f *_func) string {
|
||||
return gostringnocopy(cfuncname(f))
|
||||
}
|
||||
|
||||
func funcnameFromNameoff(f *_func, nameoff int32) string {
|
||||
datap := findmoduledatap(f.entry) // inefficient
|
||||
if datap == nil {
|
||||
return ""
|
||||
}
|
||||
cstr := &datap.pclntable[nameoff]
|
||||
return gostringnocopy(cstr)
|
||||
}
|
||||
|
||||
func funcfile(f *_func, fileno int32) string {
|
||||
datap := findmoduledatap(f.entry) // inefficient
|
||||
if datap == nil {
|
||||
return "?"
|
||||
}
|
||||
return gostringnocopy(&datap.pclntable[datap.filetab[fileno]])
|
||||
}
|
||||
|
||||
func funcline1(f *_func, targetpc uintptr, strict bool) (file string, line int32) {
|
||||
datap := findmoduledatap(f.entry) // inefficient
|
||||
if datap == nil {
|
||||
@ -699,3 +716,11 @@ func stackmapdata(stkmap *stackmap, n int32) bitvector {
|
||||
}
|
||||
return bitvector{stkmap.nbit, (*byte)(add(unsafe.Pointer(&stkmap.bytedata), uintptr(n*((stkmap.nbit+7)/8))))}
|
||||
}
|
||||
|
||||
// inlinedCall is the encoding of entries in the FUNCDATA_InlTree table.
|
||||
type inlinedCall struct {
|
||||
parent int32 // index of parent in the inltree, or < 0
|
||||
file int32 // fileno index into filetab
|
||||
line int32 // line number of the call site
|
||||
func_ int32 // offset into pclntab for name of called function
|
||||
}
|
||||
|
@ -332,6 +332,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
|
||||
}
|
||||
}
|
||||
if printing {
|
||||
// assume skip=0 for printing
|
||||
if (flags&_TraceRuntimeFrames) != 0 || showframe(f, gp, nprint == 0) {
|
||||
// Print during crash.
|
||||
// main(0x1, 0x2, 0x3)
|
||||
@ -341,6 +342,21 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
|
||||
if (n > 0 || flags&_TraceTrap == 0) && frame.pc > f.entry && !waspanic {
|
||||
tracepc--
|
||||
}
|
||||
file, line := funcline(f, tracepc)
|
||||
inldata := funcdata(f, _FUNCDATA_InlTree)
|
||||
if inldata != nil {
|
||||
inltree := (*[1 << 20]inlinedCall)(inldata)
|
||||
ix := pcdatavalue(f, _PCDATA_InlTreeIndex, tracepc, nil)
|
||||
for ix != -1 {
|
||||
name := funcnameFromNameoff(f, inltree[ix].func_)
|
||||
print(name, "(...)\n")
|
||||
print("\t", file, ":", line, "\n")
|
||||
|
||||
file = funcfile(f, inltree[ix].file)
|
||||
line = inltree[ix].line
|
||||
ix = inltree[ix].parent
|
||||
}
|
||||
}
|
||||
name := funcname(f)
|
||||
if name == "runtime.gopanic" {
|
||||
name = "panic"
|
||||
@ -358,7 +374,6 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
|
||||
print(hex(argp[i]))
|
||||
}
|
||||
print(")\n")
|
||||
file, line := funcline(f, tracepc)
|
||||
print("\t", file, ":", line)
|
||||
if frame.pc > f.entry {
|
||||
print(" +", hex(frame.pc-f.entry))
|
||||
|
Loading…
Reference in New Issue
Block a user