@@ -5,13 +5,6 @@ import (
55 "runtime"
66)
77
8- const defaultStackCap = 20
9-
10- type withStack struct {
11- origin error
12- stack []runtime.Frame
13- }
14-
158func (e * withStack ) Error () string {
169 return e .origin .Error ()
1710}
@@ -21,48 +14,88 @@ func (e *withStack) Unwrap() error {
2114}
2215
2316func (e * withStack ) StackTrace () []runtime.Frame {
24- return e .stack
17+ return e .stack . StackTrace ()
2518}
2619
27- func trace (err error , offset int ) * withStack {
28- e := withStack {
29- origin : err ,
30- stack : make ([]runtime.Frame , 0 , defaultStackCap ),
31- }
20+ type withStack struct {
21+ origin error
22+ * stack
23+ }
3224
33- for {
34- if f , ok := getFrame (offset ); ok {
35- e .stack = append (e .stack , f )
36- offset ++
37- continue
38- }
25+ // frame represents a program counter inside a stack frame.
26+ // For historical reasons if Frame is interpreted as a uintptr
27+ // its value represents the program counter + 1.
28+ type frame uintptr
3929
40- break
30+ // pc returns the program counter for this frame;
31+ // multiple frames may have the same PC value.
32+ func (f frame ) pc () uintptr { return uintptr (f ) - 1 }
33+
34+ // file returns the full path to the file that contains the
35+ // function for this Frame's pc.
36+ func (f frame ) file () string {
37+ fn := runtime .FuncForPC (f .pc ())
38+ if fn == nil {
39+ return "unknown"
4140 }
41+ file , _ := fn .FileLine (f .pc ())
42+ return file
43+ }
4244
43- return & e
45+ // line returns the line number of source code of the
46+ // function for this Frame's pc.
47+ func (f frame ) line () int {
48+ fn := runtime .FuncForPC (f .pc ())
49+ if fn == nil {
50+ return 0
51+ }
52+ _ , line := fn .FileLine (f .pc ())
53+ return line
4454}
4555
46- func getFrame (caller int ) (runtime.Frame , bool ) {
47- pc , file , line , ok := runtime .Caller (caller )
48- if ! ok {
49- return runtime.Frame {}, false
56+ // name returns the name of this function, if known.
57+ func (f frame ) name () string {
58+ fn := runtime .FuncForPC (f .pc ())
59+ if fn == nil {
60+ return "unknown"
5061 }
62+ return fn .Name ()
63+ }
5164
52- f := runtime.Frame {
53- PC : pc ,
54- File : file ,
55- Line : line ,
65+ func (f frame ) runtime () runtime.Frame {
66+ rf := runtime.Frame {
67+ PC : f .pc (),
68+ File : f .file (),
69+ Line : f .line (),
5670 }
5771
58- fn := runtime .FuncForPC (pc )
72+ fn := runtime .FuncForPC (f . pc () )
5973 if fn == nil {
60- return f , true
74+ return rf
6175 }
6276
63- f .Func = fn
64- f .Function = fn .Name ()
65- f .Entry = fn .Entry ()
77+ rf .Func = fn
78+ rf .Function = fn .Name ()
79+ rf .Entry = fn .Entry ()
80+
81+ return rf
82+ }
83+
84+ // stack represents a stack of program counters.
85+ type stack []uintptr
86+
87+ func (s * stack ) StackTrace () []runtime.Frame {
88+ f := make ([]runtime.Frame , len (* s ))
89+ for i := 0 ; i < len (f ); i ++ {
90+ f [i ] = frame ((* s )[i ]).runtime ()
91+ }
92+ return f
93+ }
6694
67- return f , true
95+ func callers () * stack {
96+ const depth = 32
97+ var pcs [depth ]uintptr
98+ n := runtime .Callers (3 , pcs [:])
99+ var st stack = pcs [0 :n ]
100+ return & st
68101}
0 commit comments