Source file src/pkg/runtime/debug/stack.go
1
2
3
4
5
6
7 package debug
8
9 import (
10 "bytes"
11 "fmt"
12 "io/ioutil"
13 "os"
14 "runtime"
15 )
16
17 var (
18 dunno = []byte("???")
19 centerDot = []byte("·")
20 dot = []byte(".")
21 )
22
23
24 func PrintStack() {
25 os.Stderr.Write(stack())
26 }
27
28
29
30
31
32
33
34 func Stack() []byte {
35 return stack()
36 }
37
38
39 func stack() []byte {
40 buf := new(bytes.Buffer)
41
42
43 var lines [][]byte
44 var lastFile string
45 for i := 2; ; i++ {
46 pc, file, line, ok := runtime.Caller(i)
47 if !ok {
48 break
49 }
50
51 fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc)
52 if file != lastFile {
53 data, err := ioutil.ReadFile(file)
54 if err != nil {
55 continue
56 }
57 lines = bytes.Split(data, []byte{'\n'})
58 lastFile = file
59 }
60 line--
61 fmt.Fprintf(buf, "\t%s: %s\n", function(pc), source(lines, line))
62 }
63 return buf.Bytes()
64 }
65
66
67 func source(lines [][]byte, n int) []byte {
68 if n < 0 || n >= len(lines) {
69 return dunno
70 }
71 return bytes.Trim(lines[n], " \t")
72 }
73
74
75 func function(pc uintptr) []byte {
76 fn := runtime.FuncForPC(pc)
77 if fn == nil {
78 return dunno
79 }
80 name := []byte(fn.Name())
81
82
83
84
85
86
87 if period := bytes.Index(name, dot); period >= 0 {
88 name = name[period+1:]
89 }
90 name = bytes.Replace(name, centerDot, dot, -1)
91 return name
92 }
View as plain text