diff --git a/src/runtime/stack_test.go b/src/runtime/stack_test.go index 24f8290f676..9a096f55389 100644 --- a/src/runtime/stack_test.go +++ b/src/runtime/stack_test.go @@ -6,6 +6,7 @@ package runtime_test import ( "fmt" + "internal/testenv" "reflect" "regexp" . "runtime" @@ -652,6 +653,8 @@ func (s structWithMethod) stack() string { func (s structWithMethod) nop() {} +func (s structWithMethod) inlinablePanic() { panic("panic") } + func TestStackWrapperCaller(t *testing.T) { var d structWithMethod // Force the compiler to construct a wrapper method. @@ -689,6 +692,33 @@ func TestStackWrapperStack(t *testing.T) { } } +func TestStackWrapperStackInlinePanic(t *testing.T) { + // Test that inline unwinding correctly tracks the callee by creating a + // stack of the form wrapper -> inlined function -> panic. If we mess up + // callee tracking, it will look like the wrapper called panic and we'll see + // the wrapper in the stack trace. + var d structWithMethod + wrapper := (*structWithMethod).inlinablePanic + defer func() { + err := recover() + if err == nil { + t.Fatalf("expected panic") + } + buf := make([]byte, 4<<10) + stk := string(buf[:Stack(buf, false)]) + if strings.Contains(stk, "") { + t.Fatalf(" appears in stack trace:\n%s", stk) + } + // Self-check: make sure inlinablePanic got inlined. + if !testenv.OptimizationOff() { + if !strings.Contains(stk, "inlinablePanic(...)") { + t.Fatalf("inlinablePanic not inlined") + } + } + }() + wrapper(&d) +} + type I interface { M() } diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go index f0d61cd994d..9dfa97f6581 100644 --- a/src/runtime/traceback.go +++ b/src/runtime/traceback.go @@ -845,7 +845,9 @@ func traceback2(u *unwinder, showRuntime bool) int { f := u.frame.fn for iu, uf := newInlineUnwinder(f, u.symPC(), noEscapePtr(&u.cache)); n < max && uf.valid(); uf = iu.next(uf) { sf := iu.srcFunc(uf) - if !(showRuntime || showframe(sf, gp, n == 0, u.calleeFuncID)) { + callee := u.calleeFuncID + u.calleeFuncID = sf.funcID + if !(showRuntime || showframe(sf, gp, n == 0, callee)) { continue }