@@ -11,7 +11,42 @@ import (
1111)
1212
1313// 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+ }
1550
1651// Format formats the frame according to the fmt.Formatter interface.
1752//
@@ -35,25 +70,16 @@ func (f Frame) format(w io.Writer, s fmt.State, verb rune) {
3570 case 's' :
3671 switch {
3772 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 ())
4576 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 ()))
5178 }
5279 case 'd' :
53- io .WriteString (w , strconv .Itoa (f .Line ))
80+ io .WriteString (w , strconv .Itoa (f .line () ))
5481 case 'n' :
55- name := f .Function
56- io .WriteString (s , funcname (name ))
82+ io .WriteString (w , funcname (f .name ()))
5783 case 'v' :
5884 f .format (w , s , 's' )
5985 io .WriteString (w , ":" )
@@ -79,9 +105,9 @@ func (st StackTrace) Format(s fmt.State, verb rune) {
79105 switch {
80106 case s .Flag ('+' ):
81107 b .Grow (len (st ) * stackMinLen )
82- for _ , fr := range st {
108+ for _ , f := range st {
83109 b .WriteByte ('\n' )
84- fr .format (& b , s , verb )
110+ f .format (& b , s , verb )
85111 }
86112 case s .Flag ('#' ):
87113 fmt .Fprintf (& b , "%#v" , []Frame (st ))
@@ -125,29 +151,20 @@ func (s *stack) Format(st fmt.State, verb rune) {
125151 case 'v' :
126152 switch {
127153 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 )
135157 }
136158 }
137159 }
138160}
139161
140162func (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 ])
149166 }
150- return st
167+ return f
151168}
152169
153170func callers () * stack {
0 commit comments