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.
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).
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
))
42 // tracebackg is used to collect stack traces from other goroutines.
43 type tracebackg
struct {
45 locbuf
[_TracebackMaxFrames
]location
49 // location is a location in the program, used for backtraces.
50 type location
struct {
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)
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 {
89 if g
.m
.throwing
> 0 && gp
!= nil && (gp
== g
.m
.curg || gp
== g
.m
.caughtsig
.ptr()) {
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" {
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{
114 _Grunnable
: "runnable",
115 _Grunning
: "running",
116 _Gsyscall
: "syscall",
117 _Gwaiting
: "waiting",
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
130 if 0 <= gpstatus
&& gpstatus
< uint32(len(gStatusStrings
)) {
131 status
= gStatusStrings
[gpstatus
]
137 if gpstatus
== _Gwaiting
&& gp
.waitreason
!= "" {
138 status
= gp
.waitreason
141 // approx time the G is blocked, in minutes
143 if (gpstatus
== _Gwaiting || gpstatus
== _Gsyscall
) && gp
.waitsince
!= 0 {
144 waitfor
= (nanotime() - gp
.waitsince
) / 60e9
146 print("goroutine ", gp
.goid
, " [", status
)
151 print(", ", waitfor
, " minutes")
153 if gp
.lockedm
!= nil {
154 print(", locked to thread")
159 // isSystemGoroutine reports whether the goroutine g must be omitted in
160 // stack dumps and deadlock detector.
161 func isSystemGoroutine(gp
*g
) bool {