summaryrefslogtreecommitdiffstats
path: root/src/runtime/symtabinl_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/symtabinl_test.go')
-rw-r--r--src/runtime/symtabinl_test.go121
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