github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/runtime/symtabinl_test.go (about) 1 // Copyright 2023 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package runtime 6 7 import ( 8 "internal/abi" 9 "runtime/internal/sys" 10 ) 11 12 func XTestInlineUnwinder(t TestingT) { 13 if TestenvOptimizationOff() { 14 t.Skip("skipping test with inlining optimizations disabled") 15 } 16 17 pc1 := abi.FuncPCABIInternal(tiuTest) 18 f := findfunc(pc1) 19 if !f.valid() { 20 t.Fatalf("failed to resolve tiuTest at PC %#x", pc1) 21 } 22 23 want := map[string]int{ 24 "tiuInlined1:3 tiuTest:10": 0, 25 "tiuInlined1:3 tiuInlined2:6 tiuTest:11": 0, 26 "tiuInlined2:7 tiuTest:11": 0, 27 "tiuTest:12": 0, 28 } 29 wantStart := map[string]int{ 30 "tiuInlined1": 2, 31 "tiuInlined2": 5, 32 "tiuTest": 9, 33 } 34 35 // Iterate over the PCs in tiuTest and walk the inline stack for each. 36 prevStack := "x" 37 for pc := pc1; pc < pc1+1024 && findfunc(pc) == f; pc += sys.PCQuantum { 38 stack := "" 39 u, uf := newInlineUnwinder(f, pc) 40 if file, _ := u.fileLine(uf); file == "?" { 41 // We're probably in the trailing function padding, where findfunc 42 // still returns f but there's no symbolic information. Just keep 43 // going until we definitely hit the end. If we see a "?" in the 44 // middle of unwinding, that's a real problem. 45 // 46 // TODO: If we ever have function end information, use that to make 47 // this robust. 48 continue 49 } 50 for ; uf.valid(); uf = u.next(uf) { 51 file, line := u.fileLine(uf) 52 const wantFile = "symtabinl_test.go" 53 if !hasSuffix(file, wantFile) { 54 t.Errorf("tiuTest+%#x: want file ...%s, got %s", pc-pc1, wantFile, file) 55 } 56 57 sf := u.srcFunc(uf) 58 59 name := sf.name() 60 const namePrefix = "runtime." 61 if hasPrefix(name, namePrefix) { 62 name = name[len(namePrefix):] 63 } 64 if !hasPrefix(name, "tiu") { 65 t.Errorf("tiuTest+%#x: unexpected function %s", pc-pc1, name) 66 } 67 68 start := int(sf.startLine) - tiuStart 69 if start != wantStart[name] { 70 t.Errorf("tiuTest+%#x: want startLine %d, got %d", pc-pc1, wantStart[name], start) 71 } 72 if sf.funcID != abi.FuncIDNormal { 73 t.Errorf("tiuTest+%#x: bad funcID %v", pc-pc1, sf.funcID) 74 } 75 76 if len(stack) > 0 { 77 stack += " " 78 } 79 stack += FmtSprintf("%s:%d", name, line-tiuStart) 80 } 81 82 if stack != prevStack { 83 prevStack = stack 84 85 t.Logf("tiuTest+%#x: %s", pc-pc1, stack) 86 87 if _, ok := want[stack]; ok { 88 want[stack]++ 89 } 90 } 91 } 92 93 // Check that we got all the stacks we wanted. 94 for stack, count := range want { 95 if count == 0 { 96 t.Errorf("missing stack %s", stack) 97 } 98 } 99 } 100 101 func lineNumber() int { 102 _, _, line, _ := Caller(1) 103 return line // return 0 for error 104 } 105 106 // Below here is the test data for XTestInlineUnwinder 107 108 var tiuStart = lineNumber() // +0 109 var tiu1, tiu2, tiu3 int // +1 110 func tiuInlined1() { // +2 111 tiu1++ // +3 112 } // +4 113 func tiuInlined2() { // +5 114 tiuInlined1() // +6 115 tiu2++ // +7 116 } // +8 117 func tiuTest() { // +9 118 tiuInlined1() // +10 119 tiuInlined2() // +11 120 tiu3++ // +12 121 } // +13