2016-11-05 Richard Biener <rguenther@suse.de>
[official-gcc.git] / libgo / go / runtime / traceback_gccgo.go
blobb102826f4228fa3be8374fa27e060406159192b6
1 // Copyright 2016 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.
5 // Traceback support for gccgo.
6 // The actual traceback code is written in C.
8 package runtime
10 import (
11 "runtime/internal/sys"
12 _ "unsafe" // for go:linkname
15 // For gccgo, use go:linkname to rename compiler-called functions to
16 // themselves, so that the compiler will export them.
17 // These are temporary for C runtime code to call.
18 //go:linkname traceback runtime.traceback
19 //go:linkname printtrace runtime.printtrace
20 //go:linkname goroutineheader runtime.goroutineheader
21 //go:linkname printcreatedby runtime.printcreatedby
23 func printcreatedby(gp *g) {
24 // Show what created goroutine, except main goroutine (goid 1).
25 pc := gp.gopc
26 tracepc := pc // back up to CALL instruction for funcfileline.
27 entry := funcentry(tracepc)
28 if entry != 0 && tracepc > entry {
29 tracepc -= sys.PCQuantum
31 function, file, line := funcfileline(tracepc, -1)
32 if function != "" && showframe(function, gp) && gp.goid != 1 {
33 print("created by ", function, "\n")
34 print("\t", file, ":", line)
35 if entry != 0 && pc > entry {
36 print(" +", hex(pc-entry))
38 print("\n")
42 // tracebackg is used to collect stack traces from other goroutines.
43 type tracebackg struct {
44 gp *g
45 locbuf [_TracebackMaxFrames]location
46 c int
49 // location is a location in the program, used for backtraces.
50 type location struct {
51 pc uintptr
52 filename string
53 function string
54 lineno int
57 //extern runtime_callers
58 func c_callers(skip int32, locbuf *location, max int32, keepThunks bool) int32
60 // callers returns a stack trace of the current goroutine.
61 // The gc version of callers takes []uintptr, but we take []location.
62 func callers(skip int, locbuf []location) int {
63 n := c_callers(int32(skip), &locbuf[0], int32(len(locbuf)), false)
64 return int(n)
67 // traceback prints a traceback of the current goroutine.
68 // This differs from the gc version, which is given pc, sp, lr and g and
69 // can print a traceback of any goroutine.
70 func traceback(skip int32) {
71 var locbuf [100]location
72 c := c_callers(skip+1, &locbuf[0], int32(len(locbuf)), false)
73 printtrace(locbuf[:c], getg())
76 // printtrace prints a traceback from locbuf.
77 func printtrace(locbuf []location, gp *g) {
78 for i := range locbuf {
79 if showframe(locbuf[i].function, gp) {
80 print(locbuf[i].function, "\n\t", locbuf[i].filename, ":", locbuf[i].lineno, "\n")
85 // showframe returns whether to print a frame in a traceback.
86 // name is the function name.
87 func showframe(name string, gp *g) bool {
88 g := getg()
89 if g.m.throwing > 0 && gp != nil && (gp == g.m.curg || gp == g.m.caughtsig.ptr()) {
90 return true
92 level, _, _ := gotraceback()
94 // Special case: always show runtime.gopanic frame, so that we can
95 // see where a panic started in the middle of a stack trace.
96 // See golang.org/issue/5832.
97 // __go_panic is the current gccgo name.
98 if name == "runtime.gopanic" || name == "__go_panic" {
99 return true
102 return level > 1 || contains(name, ".") && (!hasprefix(name, "runtime.") || isExportedRuntime(name))
105 // isExportedRuntime reports whether name is an exported runtime function.
106 // It is only for runtime functions, so ASCII A-Z is fine.
107 func isExportedRuntime(name string) bool {
108 const n = len("runtime.")
109 return len(name) > n && name[:n] == "runtime." && 'A' <= name[n] && name[n] <= 'Z'
112 var gStatusStrings = [...]string{
113 _Gidle: "idle",
114 _Grunnable: "runnable",
115 _Grunning: "running",
116 _Gsyscall: "syscall",
117 _Gwaiting: "waiting",
118 _Gdead: "dead",
119 _Gcopystack: "copystack",
122 func goroutineheader(gp *g) {
123 gpstatus := readgstatus(gp)
125 isScan := gpstatus&_Gscan != 0
126 gpstatus &^= _Gscan // drop the scan bit
128 // Basic string status
129 var status string
130 if 0 <= gpstatus && gpstatus < uint32(len(gStatusStrings)) {
131 status = gStatusStrings[gpstatus]
132 } else {
133 status = "???"
136 // Override.
137 if gpstatus == _Gwaiting && gp.waitreason != "" {
138 status = gp.waitreason
141 // approx time the G is blocked, in minutes
142 var waitfor int64
143 if (gpstatus == _Gwaiting || gpstatus == _Gsyscall) && gp.waitsince != 0 {
144 waitfor = (nanotime() - gp.waitsince) / 60e9
146 print("goroutine ", gp.goid, " [", status)
147 if isScan {
148 print(" (scan)")
150 if waitfor >= 1 {
151 print(", ", waitfor, " minutes")
153 if gp.lockedm != nil {
154 print(", locked to thread")
156 print("]:\n")
159 // isSystemGoroutine reports whether the goroutine g must be omitted in
160 // stack dumps and deadlock detector.
161 func isSystemGoroutine(gp *g) bool {
162 // FIXME.
163 return false