@@ -11,7 +11,42 @@ import (
11
11
)
12
12
13
13
// Frame represents a program counter inside a stack frame.
14
- type Frame runtime.Frame
14
+ type Frame uintptr
15
+
16
+ // pc returns the program counter for this frame;
17
+ // multiple frames may have the same PC value.
18
+ func (f Frame ) pc () uintptr { return uintptr (f ) - 1 }
19
+
20
+ // file returns the full path to the file that contains the
21
+ // function for this Frame's pc.
22
+ func (f Frame ) file () string {
23
+ fn := runtime .FuncForPC (f .pc ())
24
+ if fn == nil {
25
+ return "unknown"
26
+ }
27
+ file , _ := fn .FileLine (f .pc ())
28
+ return file
29
+ }
30
+
31
+ // line returns the line number of source code of the
32
+ // function for this Frame's pc.
33
+ func (f Frame ) line () int {
34
+ fn := runtime .FuncForPC (f .pc ())
35
+ if fn == nil {
36
+ return 0
37
+ }
38
+ _ , line := fn .FileLine (f .pc ())
39
+ return line
40
+ }
41
+
42
+ // name returns the name of this function, if known.
43
+ func (f Frame ) name () string {
44
+ fn := runtime .FuncForPC (f .pc ())
45
+ if fn == nil {
46
+ return "unknown"
47
+ }
48
+ return fn .Name ()
49
+ }
15
50
16
51
// Format formats the frame according to the fmt.Formatter interface.
17
52
//
@@ -35,25 +70,16 @@ func (f Frame) format(w io.Writer, s fmt.State, verb rune) {
35
70
case 's' :
36
71
switch {
37
72
case s .Flag ('+' ):
38
- if f .Function == "" {
39
- io .WriteString (w , "unknown" )
40
- } else {
41
- io .WriteString (w , f .Function )
42
- io .WriteString (w , "\n \t " )
43
- io .WriteString (w , f .File )
44
- }
73
+ io .WriteString (w , f .name ())
74
+ io .WriteString (w , "\n \t " )
75
+ io .WriteString (w , f .file ())
45
76
default :
46
- file := f .File
47
- if file == "" {
48
- file = "unknown"
49
- }
50
- io .WriteString (w , path .Base (file ))
77
+ io .WriteString (w , path .Base (f .file ()))
51
78
}
52
79
case 'd' :
53
- io .WriteString (w , strconv .Itoa (f .Line ))
80
+ io .WriteString (w , strconv .Itoa (f .line () ))
54
81
case 'n' :
55
- name := f .Function
56
- io .WriteString (s , funcname (name ))
82
+ io .WriteString (w , funcname (f .name ()))
57
83
case 'v' :
58
84
f .format (w , s , 's' )
59
85
io .WriteString (w , ":" )
@@ -79,9 +105,9 @@ func (st StackTrace) Format(s fmt.State, verb rune) {
79
105
switch {
80
106
case s .Flag ('+' ):
81
107
b .Grow (len (st ) * stackMinLen )
82
- for _ , fr := range st {
108
+ for _ , f := range st {
83
109
b .WriteByte ('\n' )
84
- fr .format (& b , s , verb )
110
+ f .format (& b , s , verb )
85
111
}
86
112
case s .Flag ('#' ):
87
113
fmt .Fprintf (& b , "%#v" , []Frame (st ))
@@ -125,29 +151,20 @@ func (s *stack) Format(st fmt.State, verb rune) {
125
151
case 'v' :
126
152
switch {
127
153
case st .Flag ('+' ):
128
- frames := runtime .CallersFrames (* s )
129
- for {
130
- frame , more := frames .Next ()
131
- fmt .Fprintf (st , "\n %+v" , Frame (frame ))
132
- if ! more {
133
- break
134
- }
154
+ for _ , pc := range * s {
155
+ f := Frame (pc )
156
+ fmt .Fprintf (st , "\n %+v" , f )
135
157
}
136
158
}
137
159
}
138
160
}
139
161
140
162
func (s * stack ) StackTrace () StackTrace {
141
- var st []Frame
142
- frames := runtime .CallersFrames (* s )
143
- for {
144
- frame , more := frames .Next ()
145
- st = append (st , Frame (frame ))
146
- if ! more {
147
- break
148
- }
163
+ f := make ([]Frame , len (* s ))
164
+ for i := 0 ; i < len (f ); i ++ {
165
+ f [i ] = Frame ((* s )[i ])
149
166
}
150
- return st
167
+ return f
151
168
}
152
169
153
170
func callers () * stack {
0 commit comments