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.
4
5// Traceback support for gccgo.
6// The actual traceback code is written in C.
7
8package runtime
9
10import (
11	"internal/bytealg"
12	"runtime/internal/sys"
13	"unsafe"
14)
15
16func printcreatedby(gp *g) {
17	// Show what created goroutine, except main goroutine (goid 1).
18	pc := gp.gopc
19	tracepc := pc // back up to CALL instruction for funcfileline.
20	entry := funcentry(tracepc)
21	if entry != 0 && tracepc > entry {
22		tracepc -= sys.PCQuantum
23	}
24	function, file, line, _ := funcfileline(tracepc, -1, false)
25	if function != "" && showframe(function, gp, false) && gp.goid != 1 {
26		printcreatedby1(function, file, line, entry, pc)
27	}
28}
29
30func printcreatedby1(function, file string, line int, entry, pc uintptr) {
31	print("created by ", function, "\n")
32	print("\t", file, ":", line)
33	if entry != 0 && pc > entry {
34		print(" +", hex(pc-entry))
35	}
36	print("\n")
37}
38
39// tracebackg is used to collect stack traces from other goroutines.
40type tracebackg struct {
41	gp     *g
42	locbuf [_TracebackMaxFrames]location
43	c      int
44}
45
46// location is a location in the program, used for backtraces.
47type location struct {
48	pc       uintptr
49	filename string
50	function string
51	lineno   int
52}
53
54//go:noescape
55//extern runtime_callers
56func c_callers(skip int32, locbuf *location, max int32, keepThunks bool) int32
57
58// callers returns a stack trace of the current goroutine.
59// The gc version of callers takes []uintptr, but we take []location.
60func callers(skip int, locbuf []location) int {
61	n := c_callers(int32(skip)+1, &locbuf[0], int32(len(locbuf)), false)
62	return int(n)
63}
64
65//go:noescape
66//extern runtime_callersRaw
67func c_callersRaw(pcs *uintptr, max int32) int32
68
69// callersRaw returns a raw (PCs only) stack trace of the current goroutine.
70func callersRaw(pcbuf []uintptr) int {
71	n := c_callersRaw(&pcbuf[0], int32(len(pcbuf)))
72	return int(n)
73}
74
75// traceback prints a traceback of the current goroutine.
76// This differs from the gc version, which is given pc, sp, lr and g and
77// can print a traceback of any goroutine.
78func traceback(skip int32) {
79	var locbuf [100]location
80	c := c_callers(skip+1, &locbuf[0], int32(len(locbuf)), false)
81	gp := getg()
82	printtrace(locbuf[:c], gp)
83	printcreatedby(gp)
84
85	if gp.ancestors == nil {
86		return
87	}
88	for _, ancestor := range *gp.ancestors {
89		printAncestorTraceback(ancestor)
90	}
91}
92
93// printAncestorTraceback prints the traceback of the given ancestor.
94func printAncestorTraceback(ancestor ancestorInfo) {
95	print("[originating from goroutine ", ancestor.goid, "]:\n")
96	for fidx, pc := range ancestor.pcs {
97		function, file, line, _ := funcfileline(pc, -1, false)
98		if showfuncinfo(function, fidx == 0) {
99			printAncestorTracebackFuncInfo(function, file, line, pc)
100		}
101	}
102	if len(ancestor.pcs) == _TracebackMaxFrames {
103		print("...additional frames elided...\n")
104	}
105	// Show what created goroutine, except main goroutine (goid 1).
106	function, file, line, _ := funcfileline(ancestor.gopc, -1, false)
107	if function != "" && showfuncinfo(function, false) && ancestor.goid != 1 {
108		printcreatedby1(function, file, line, funcentry(ancestor.gopc), ancestor.gopc)
109	}
110}
111
112// printAncestorTraceback prints the given function info at a given pc
113// within an ancestor traceback. The precision of this info is reduced
114// due to only have access to the pcs at the time of the caller
115// goroutine being created.
116func printAncestorTracebackFuncInfo(name, file string, line int, pc uintptr) {
117	if name == "runtime.gopanic" {
118		name = "panic"
119	}
120	print(name, "(...)\n")
121	print("\t", file, ":", line)
122	entry := funcentry(pc)
123	if pc > entry {
124		print(" +", hex(pc-entry))
125	}
126	print("\n")
127}
128
129// printtrace prints a traceback from locbuf.
130func printtrace(locbuf []location, gp *g) {
131	nprint := 0
132	for i := range locbuf {
133		if showframe(locbuf[i].function, gp, nprint == 0) {
134			name := locbuf[i].function
135			if name == "runtime.gopanic" {
136				name = "panic"
137			}
138			print(name, "\n\t", locbuf[i].filename, ":", locbuf[i].lineno, "\n")
139			nprint++
140		}
141	}
142}
143
144// showframe returns whether to print a frame in a traceback.
145// name is the function name.
146func showframe(name string, gp *g, firstFrame bool) bool {
147	g := getg()
148	if g.m.throwing > 0 && gp != nil && (gp == g.m.curg || gp == g.m.caughtsig.ptr()) {
149		return true
150	}
151	return showfuncinfo(name, firstFrame)
152}
153
154func showfuncinfo(name string, firstFrame bool) bool {
155	// Gccgo can trace back through C functions called via cgo.
156	// We want to print those in the traceback.
157	// But unless GOTRACEBACK > 1 (checked below), still skip
158	// internal C functions and cgo-generated functions.
159	if name != "" && bytealg.IndexByteString(name, '.') < 0 && !hasPrefix(name, "__go_") && !hasPrefix(name, "_cgo_") {
160		return true
161	}
162
163	level, _, _ := gotraceback()
164	if level > 1 {
165		// Show all frames.
166		return true
167	}
168
169	if name == "" {
170		return false
171	}
172
173	// Special case: always show runtime.gopanic frame
174	// in the middle of a stack trace, so that we can
175	// see the boundary between ordinary code and
176	// panic-induced deferred code.
177	// See golang.org/issue/5832.
178	if name == "runtime.gopanic" && !firstFrame {
179		return true
180	}
181
182	return bytealg.IndexByteString(name, '.') >= 0 && (!hasPrefix(name, "runtime.") || isExportedRuntime(name))
183}
184
185// isExportedRuntime reports whether name is an exported runtime function.
186// It is only for runtime functions, so ASCII A-Z is fine. Here also check
187// for mangled functions from runtime/<...>, which will be prefixed with
188// "runtime_1".
189func isExportedRuntime(name string) bool {
190	const n = len("runtime.")
191	if hasPrefix(name, "runtime_1") {
192		return true
193	}
194	return len(name) > n && name[:n] == "runtime." && 'A' <= name[n] && name[n] <= 'Z'
195}
196
197var gStatusStrings = [...]string{
198	_Gidle:           "idle",
199	_Grunnable:       "runnable",
200	_Grunning:        "running",
201	_Gsyscall:        "syscall",
202	_Gwaiting:        "waiting",
203	_Gdead:           "dead",
204	_Gcopystack:      "copystack",
205	_Gexitingsyscall: "exiting syscall",
206}
207
208func goroutineheader(gp *g) {
209	gpstatus := readgstatus(gp)
210
211	isScan := gpstatus&_Gscan != 0
212	gpstatus &^= _Gscan // drop the scan bit
213
214	// Basic string status
215	var status string
216	if 0 <= gpstatus && gpstatus < uint32(len(gStatusStrings)) {
217		status = gStatusStrings[gpstatus]
218	} else {
219		status = "???"
220	}
221
222	// Override.
223	if gpstatus == _Gwaiting && gp.waitreason != waitReasonZero {
224		status = gp.waitreason.String()
225	}
226
227	// approx time the G is blocked, in minutes
228	var waitfor int64
229	if (gpstatus == _Gwaiting || gpstatus == _Gsyscall) && gp.waitsince != 0 {
230		waitfor = (nanotime() - gp.waitsince) / 60e9
231	}
232	print("goroutine ", gp.goid, " [", status)
233	if isScan {
234		print(" (scan)")
235	}
236	if waitfor >= 1 {
237		print(", ", waitfor, " minutes")
238	}
239	if gp.lockedm != 0 {
240		print(", locked to thread")
241	}
242	print("]:\n")
243}
244
245// isSystemGoroutine reports whether the goroutine g must be omitted
246// in stack dumps and deadlock detector. This is any goroutine that
247// starts at a runtime.* entry point, except for runtime.main and
248// sometimes runtime.runfinq.
249//
250// If fixed is true, any goroutine that can vary between user and
251// system (that is, the finalizer goroutine) is considered a user
252// goroutine.
253func isSystemGoroutine(gp *g, fixed bool) bool {
254	if !gp.isSystemGoroutine {
255		return false
256	}
257	if fixed && gp.isFinalizerGoroutine {
258		// This goroutine can vary. In fixed mode,
259		// always consider it a user goroutine.
260		return false
261	}
262	return true
263}
264
265func tracebackothers(me *g) {
266	var tb tracebackg
267	tb.gp = me
268
269	// The getTraceback function will modify me's stack context.
270	// Preserve it in case we have been called via systemstack.
271	context := me.context
272	stackcontext := me.stackcontext
273
274	level, _, _ := gotraceback()
275
276	// Show the current goroutine first, if we haven't already.
277	g := getg()
278	gp := g.m.curg
279	if gp != nil && gp != me {
280		print("\n")
281		goroutineheader(gp)
282		gp.traceback = (uintptr)(noescape(unsafe.Pointer(&tb)))
283		getTraceback(me, gp)
284		printtrace(tb.locbuf[:tb.c], nil)
285		printcreatedby(gp)
286	}
287
288	lock(&allglock)
289	for _, gp := range allgs {
290		if gp == me || gp == g.m.curg || readgstatus(gp) == _Gdead || isSystemGoroutine(gp, false) && level < 2 {
291			continue
292		}
293		print("\n")
294		goroutineheader(gp)
295
296		// gccgo's only mechanism for doing a stack trace is
297		// _Unwind_Backtrace.  And that only works for the
298		// current thread, not for other random goroutines.
299		// So we need to switch context to the goroutine, get
300		// the backtrace, and then switch back.
301		//
302		// This means that if g is running or in a syscall, we
303		// can't reliably print a stack trace.  FIXME.
304
305		// Note: gp.m == g.m occurs when tracebackothers is
306		// called from a signal handler initiated during a
307		// systemstack call. The original G is still in the
308		// running state, and we want to print its stack.
309		if gp.m != g.m && readgstatus(gp)&^_Gscan == _Grunning {
310			print("\tgoroutine running on other thread; stack unavailable\n")
311			printcreatedby(gp)
312		} else if readgstatus(gp)&^_Gscan == _Gsyscall {
313			print("\tgoroutine in C code; stack unavailable\n")
314			printcreatedby(gp)
315		} else {
316			gp.traceback = (uintptr)(noescape(unsafe.Pointer(&tb)))
317			getTraceback(me, gp)
318			printtrace(tb.locbuf[:tb.c], nil)
319			printcreatedby(gp)
320		}
321	}
322	unlock(&allglock)
323
324	me.context = context
325	me.stackcontext = stackcontext
326}
327