1 // Copyright 2014 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.
9 _
"unsafe" // for go:linkname
12 // Frames may be used to get function/file/line information for a
13 // slice of PC values returned by Callers.
15 // callers is a slice of PCs that have not yet been expanded to frames.
18 // The last PC we saw.
21 // The number of times we've seen last.
25 // Frame is the information returned by Frames for each call frame.
27 // PC is the program counter for the location in this frame.
28 // For a frame that calls another frame, this will be the
29 // program counter of a call instruction. Because of inlining,
30 // multiple frames may have the same PC value, but different
31 // symbolic information.
34 // Func is the Func value of this call frame. This may be nil
35 // for non-Go code or fully inlined functions.
38 // Function is the package path-qualified function name of
39 // this call frame. If non-empty, this string uniquely
40 // identifies a single function in the program.
41 // This may be the empty string if not known.
42 // If Func is not nil then Function == Func.Name().
45 // File and Line are the file name and line number of the
46 // location in this frame. For non-leaf frames, this will be
47 // the location of a call. These may be the empty string and
48 // zero, respectively, if not known.
52 // Entry point program counter for the function; may be zero
53 // if not known. If Func is not nil then Entry ==
58 // CallersFrames takes a slice of PC values returned by Callers and
59 // prepares to return function/file/line information.
60 // Do not change the slice until you are done with the Frames.
61 func CallersFrames(callers
[]uintptr) *Frames
{
62 return &Frames
{callers
: callers
}
65 // Next returns a Frame representing the next call frame in the slice
66 // of PC values. If it has already returned all call frames, Next
67 // returns a zero Frame.
69 // The more result indicates whether the next call to Next will return
70 // a valid Frame. It does not necessarily indicate whether this call
73 // See the Frames example for idiomatic usage.
74 func (ci
*Frames
) Next() (frame Frame
, more
bool) {
75 if len(ci
.callers
) == 0 {
80 ci
.callers
= ci
.callers
[1:]
90 more
= len(ci
.callers
) > 0
92 // Subtract 1 from PC to undo the 1 we added in callback in
94 function
, file
, line
, _
:= funcfileline(pc
-1, int32(i
), more
)
95 if function
== "" && file
== "" {
99 // Demangle function name if needed.
100 function
= demangleSymbol(function
)
103 entry
:= funcentry(pc
- 1)
104 f
:= &Func
{name
: function
, entry
: entry
}
124 // pcInlineCallers is written in C.
125 func pcInlineCallers(pc
uintptr, locbuf
*location
, max
int32) int32
127 // runtime_expandFinalInlineFrame expands the final pc in stk to include all
128 // "callers" if pc is inline.
130 //go:linkname runtime_expandFinalInlineFrame runtime_1pprof.runtime__expandFinalInlineFrame
131 func runtime_expandFinalInlineFrame(stk
[]uintptr) []uintptr {
135 pc
:= stk
[len(stk
)-1]
138 var locbuf
[_TracebackMaxFrames
]location
139 n
:= pcInlineCallers(tracepc
, &locbuf
[0], int32(len(locbuf
)))
141 // Returning the same PC several times causes Frame.Next to do
143 for i
:= int32(1); i
< n
; i
++ {
144 stk
= append(stk
, pc
)
150 // NOTE: Func does not expose the actual unexported fields, because we return *Func
151 // values to users, and we want to keep them from being able to overwrite the data
152 // with (say) *f = Func{}.
153 // All code operating on a *Func must call raw() to get the *_func
154 // or funcInfo() to get the funcInfo instead.
156 // A Func represents a Go function in the running binary.
162 // FuncForPC returns a *Func describing the function that contains the
163 // given program counter address, or else nil.
165 // If pc represents multiple functions because of inlining, it returns
166 // the *Func describing the innermost function, but with an entry of
167 // the outermost function.
168 func FuncForPC(pc
uintptr) *Func
{
169 name
, _
, _
, _
:= funcfileline(pc
, -1, false)
173 entry
:= funcentry(pc
)
174 return &Func
{name
: name
, entry
: entry
}
177 // Name returns the name of the function.
178 func (f
*Func
) Name() string {
185 // Entry returns the entry address of the function.
186 func (f
*Func
) Entry() uintptr {
193 // FileLine returns the file name and line number of the
194 // source code corresponding to the program counter pc.
195 // The result will not be accurate if pc is not a program
197 func (f
*Func
) FileLine(pc
uintptr) (file
string, line
int) {
198 _
, file
, line
, _
= funcfileline(pc
, -1, false)
202 func hexval(b
byte) uint {
203 if b
>= '0' && b
<= '9' {
206 if b
>= 'a' && b
<= 'f' {
207 return uint(b
-'a') + 10
212 func hexDigitsToRune(digits
[]byte, ndig
int) rune
{
214 for i
:= 0; i
< ndig
; i
++ {
216 result |
= hexval(digits
[i
])
221 // decodeIdentifier performs an in-place decoding on the input byte slice.
222 // This undoes the compiler underscore mangling.
223 // Returns the number of bytes used by the result.
224 func decodeIdentifier(bsl
[]byte) int {
225 underscoreCodes
:= map[byte]byte{
243 for i
:= 0; i
< len(bsl
); i
++ {
245 if b
!= '_' || i
+1 >= len(bsl
) {
251 if d
, ok
:= underscoreCodes
[bsl
[i
+1]]; ok
{
268 if rlen
> 0 && i
+1+rlen
< len(bsl
) {
269 r
:= hexDigitsToRune(bsl
[i
+2:], rlen
)
270 nc
:= encoderune(bsl
[j
:], r
)
281 // Demangle a function symbol. Applies the reverse of go_encode_id()
282 // as used in the compiler.
284 func demangleSymbol(s
string) string {
285 if bytealg
.IndexByteString(s
, '.') < 0 {
286 // A symbol with no '.' is not a Go symbol.
291 nchars
:= decodeIdentifier(bsl
)
296 // implemented in go-caller.c
297 func funcfileline(uintptr, int32, bool) (string, string, int, int)
298 func funcentry(uintptr) uintptr