@@ -116,28 +116,21 @@ func (ci *Frames) Next() (frame Frame, more bool) {
116
116
// work correctly for entries in the result of runtime.Callers.
117
117
pc --
118
118
}
119
- name := funcname (funcInfo )
120
- startLine := f .startLine ()
121
- if inldata := funcdata (funcInfo , _FUNCDATA_InlTree ); inldata != nil {
122
- inltree := (* [1 << 20 ]inlinedCall )(inldata )
123
- // Non-strict as cgoTraceback may have added bogus PCs
124
- // with a valid funcInfo but invalid PCDATA.
125
- ix := pcdatavalue1 (funcInfo , _PCDATA_InlTreeIndex , pc , nil , false )
126
- if ix >= 0 {
127
- // Note: entry is not modified. It always refers to a real frame, not an inlined one.
128
- f = nil
129
- ic := inltree [ix ]
130
- name = funcnameFromNameOff (funcInfo , ic .nameOff )
131
- startLine = ic .startLine
132
- // File/line from funcline1 below are already correct.
133
- }
119
+ // It's important that interpret pc non-strictly as cgoTraceback may
120
+ // have added bogus PCs with a valid funcInfo but invalid PCDATA.
121
+ u , uf := newInlineUnwinder (funcInfo , pc , nil )
122
+ sf := u .srcFunc (uf )
123
+ if u .isInlined (uf ) {
124
+ // Note: entry is not modified. It always refers to a real frame, not an inlined one.
125
+ // File/line from funcline1 below are already correct.
126
+ f = nil
134
127
}
135
128
ci .frames = append (ci .frames , Frame {
136
129
PC : pc ,
137
130
Func : f ,
138
- Function : name ,
131
+ Function : sf . name () ,
139
132
Entry : entry ,
140
- startLine : int (startLine ),
133
+ startLine : int (sf . startLine ),
141
134
funcInfo : funcInfo ,
142
135
// Note: File,Line set below
143
136
})
@@ -182,6 +175,8 @@ func runtime_FrameStartLine(f *Frame) int {
182
175
//
183
176
//go:linkname runtime_expandFinalInlineFrame runtime/pprof.runtime_expandFinalInlineFrame
184
177
func runtime_expandFinalInlineFrame (stk []uintptr ) []uintptr {
178
+ // TODO: It would be more efficient to report only physical PCs to pprof and
179
+ // just expand the whole stack.
185
180
if len (stk ) == 0 {
186
181
return stk
187
182
}
@@ -194,46 +189,29 @@ func runtime_expandFinalInlineFrame(stk []uintptr) []uintptr {
194
189
return stk
195
190
}
196
191
197
- inldata := funcdata (f , _FUNCDATA_InlTree )
198
- if inldata == nil {
199
- // Nothing inline in f.
192
+ var cache pcvalueCache
193
+ u , uf := newInlineUnwinder (f , tracepc , & cache )
194
+ if ! u .isInlined (uf ) {
195
+ // Nothing inline at tracepc.
200
196
return stk
201
197
}
202
198
203
199
// Treat the previous func as normal. We haven't actually checked, but
204
200
// since this pc was included in the stack, we know it shouldn't be
205
201
// elided.
206
- lastFuncID := funcID_normal
202
+ calleeID := funcID_normal
207
203
208
204
// Remove pc from stk; we'll re-add it below.
209
205
stk = stk [:len (stk )- 1 ]
210
206
211
- // See inline expansion in gentraceback.
212
- var cache pcvalueCache
213
- inltree := (* [1 << 20 ]inlinedCall )(inldata )
214
- for {
215
- // Non-strict as cgoTraceback may have added bogus PCs
216
- // with a valid funcInfo but invalid PCDATA.
217
- ix := pcdatavalue1 (f , _PCDATA_InlTreeIndex , tracepc , & cache , false )
218
- if ix < 0 {
219
- break
220
- }
221
- if inltree [ix ].funcID == funcID_wrapper && elideWrapperCalling (lastFuncID ) {
207
+ for ; uf .valid (); uf = u .next (uf ) {
208
+ funcID := u .srcFunc (uf ).funcID
209
+ if funcID == funcID_wrapper && elideWrapperCalling (calleeID ) {
222
210
// ignore wrappers
223
211
} else {
224
- stk = append (stk , pc )
212
+ stk = append (stk , uf . pc + 1 )
225
213
}
226
- lastFuncID = inltree [ix ].funcID
227
- // Back up to an instruction in the "caller".
228
- tracepc = f .entry () + uintptr (inltree [ix ].parentPc )
229
- pc = tracepc + 1
230
- }
231
-
232
- // N.B. we want to keep the last parentPC which is not inline.
233
- if f .funcID == funcID_wrapper && elideWrapperCalling (lastFuncID ) {
234
- // Ignore wrapper functions (except when they trigger panics).
235
- } else {
236
- stk = append (stk , pc )
214
+ calleeID = funcID
237
215
}
238
216
239
217
return stk
@@ -752,28 +730,25 @@ func FuncForPC(pc uintptr) *Func {
752
730
if ! f .valid () {
753
731
return nil
754
732
}
755
- if inldata := funcdata (f , _FUNCDATA_InlTree ); inldata != nil {
756
- // Note: strict=false so bad PCs (those between functions) don't crash the runtime.
757
- // We just report the preceding function in that situation. See issue 29735.
758
- // TODO: Perhaps we should report no function at all in that case.
759
- // The runtime currently doesn't have function end info, alas.
760
- if ix := pcdatavalue1 (f , _PCDATA_InlTreeIndex , pc , nil , false ); ix >= 0 {
761
- inltree := (* [1 << 20 ]inlinedCall )(inldata )
762
- ic := inltree [ix ]
763
- name := funcnameFromNameOff (f , ic .nameOff )
764
- file , line := funcline (f , pc )
765
- fi := & funcinl {
766
- ones : ^ uint32 (0 ),
767
- entry : f .entry (), // entry of the real (the outermost) function.
768
- name : name ,
769
- file : file ,
770
- line : line ,
771
- startLine : ic .startLine ,
772
- }
773
- return (* Func )(unsafe .Pointer (fi ))
774
- }
733
+ // This must interpret PC non-strictly so bad PCs (those between functions) don't crash the runtime.
734
+ // We just report the preceding function in that situation. See issue 29735.
735
+ // TODO: Perhaps we should report no function at all in that case.
736
+ // The runtime currently doesn't have function end info, alas.
737
+ u , uf := newInlineUnwinder (f , pc , nil )
738
+ if ! u .isInlined (uf ) {
739
+ return f ._Func ()
775
740
}
776
- return f ._Func ()
741
+ sf := u .srcFunc (uf )
742
+ file , line := u .fileLine (uf )
743
+ fi := & funcinl {
744
+ ones : ^ uint32 (0 ),
745
+ entry : f .entry (), // entry of the real (the outermost) function.
746
+ name : sf .name (),
747
+ file : file ,
748
+ line : int32 (line ),
749
+ startLine : sf .startLine ,
750
+ }
751
+ return (* Func )(unsafe .Pointer (fi ))
777
752
}
778
753
779
754
// Name returns the name of the function.
@@ -1059,13 +1034,6 @@ func funcpkgpath(f funcInfo) string {
1059
1034
return name [:i ]
1060
1035
}
1061
1036
1062
- func funcnameFromNameOff (f funcInfo , nameOff int32 ) string {
1063
- if ! f .valid () {
1064
- return ""
1065
- }
1066
- return f .datap .funcName (nameOff )
1067
- }
1068
-
1069
1037
func funcfile (f funcInfo , fileno int32 ) string {
1070
1038
datap := f .datap
1071
1039
if ! f .valid () {
0 commit comments