diff options
Diffstat (limited to 'src/runtime/symtabinl_test.go')
-rw-r--r-- | src/runtime/symtabinl_test.go | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/runtime/symtabinl_test.go b/src/runtime/symtabinl_test.go new file mode 100644 index 0000000..df524ae --- /dev/null +++ b/src/runtime/symtabinl_test.go @@ -0,0 +1,121 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime + +import ( + "internal/abi" + "runtime/internal/sys" +) + +func XTestInlineUnwinder(t TestingT) { + if TestenvOptimizationOff() { + t.Skip("skipping test with inlining optimizations disabled") + } + + pc1 := abi.FuncPCABIInternal(tiuTest) + f := findfunc(pc1) + if !f.valid() { + t.Fatalf("failed to resolve tiuTest at PC %#x", pc1) + } + + want := map[string]int{ + "tiuInlined1:3 tiuTest:10": 0, + "tiuInlined1:3 tiuInlined2:6 tiuTest:11": 0, + "tiuInlined2:7 tiuTest:11": 0, + "tiuTest:12": 0, + } + wantStart := map[string]int{ + "tiuInlined1": 2, + "tiuInlined2": 5, + "tiuTest": 9, + } + + // Iterate over the PCs in tiuTest and walk the inline stack for each. + prevStack := "x" + for pc := pc1; pc < pc1+1024 && findfunc(pc) == f; pc += sys.PCQuantum { + stack := "" + u, uf := newInlineUnwinder(f, pc) + if file, _ := u.fileLine(uf); file == "?" { + // We're probably in the trailing function padding, where findfunc + // still returns f but there's no symbolic information. Just keep + // going until we definitely hit the end. If we see a "?" in the + // middle of unwinding, that's a real problem. + // + // TODO: If we ever have function end information, use that to make + // this robust. + continue + } + for ; uf.valid(); uf = u.next(uf) { + file, line := u.fileLine(uf) + const wantFile = "symtabinl_test.go" + if !hasSuffix(file, wantFile) { + t.Errorf("tiuTest+%#x: want file ...%s, got %s", pc-pc1, wantFile, file) + } + + sf := u.srcFunc(uf) + + name := sf.name() + const namePrefix = "runtime." + if hasPrefix(name, namePrefix) { + name = name[len(namePrefix):] + } + if !hasPrefix(name, "tiu") { + t.Errorf("tiuTest+%#x: unexpected function %s", pc-pc1, name) + } + + start := int(sf.startLine) - tiuStart + if start != wantStart[name] { + t.Errorf("tiuTest+%#x: want startLine %d, got %d", pc-pc1, wantStart[name], start) + } + if sf.funcID != abi.FuncIDNormal { + t.Errorf("tiuTest+%#x: bad funcID %v", pc-pc1, sf.funcID) + } + + if len(stack) > 0 { + stack += " " + } + stack += FmtSprintf("%s:%d", name, line-tiuStart) + } + + if stack != prevStack { + prevStack = stack + + t.Logf("tiuTest+%#x: %s", pc-pc1, stack) + + if _, ok := want[stack]; ok { + want[stack]++ + } + } + } + + // Check that we got all the stacks we wanted. + for stack, count := range want { + if count == 0 { + t.Errorf("missing stack %s", stack) + } + } +} + +func lineNumber() int { + _, _, line, _ := Caller(1) + return line // return 0 for error +} + +// Below here is the test data for XTestInlineUnwinder + +var tiuStart = lineNumber() // +0 +var tiu1, tiu2, tiu3 int // +1 +func tiuInlined1() { // +2 + tiu1++ // +3 +} // +4 +func tiuInlined2() { // +5 + tiuInlined1() // +6 + tiu2++ // +7 +} // +8 +func tiuTest() { // +9 + tiuInlined1() // +10 + tiuInlined2() // +11 + tiu3++ // +12 +} // +13 |