1 // Copyright 2009 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.
9 "runtime/internal/atomic"
13 // For gccgo, use go:linkname to export compiler-called functions.
15 //go:linkname printbool
16 //go:linkname printfloat
17 //go:linkname printint
18 //go:linkname printhex
19 //go:linkname printuint
20 //go:linkname printcomplex
21 //go:linkname printstring
22 //go:linkname printpointer
23 //go:linkname printiface
24 //go:linkname printeface
25 //go:linkname printslice
28 //go:linkname printlock
29 //go:linkname printunlock
30 // Temporary for C code to call:
32 //go:linkname printhex
34 // The compiler knows that a print of a value of this type
35 // should use printhex instead of printuint (decimal).
39 func bytes(s
string) (ret
[]byte) {
40 rp
:= (*slice
)(unsafe
.Pointer(&ret
))
41 sp
:= stringStructOf(&s
)
49 // printBacklog is a circular buffer of messages written with the builtin
50 // print* functions, for use in postmortem analysis of core dumps.
51 printBacklog
[512]byte
55 // recordForPanic maintains a circular buffer of messages written by the
56 // runtime leading up to a process crash, allowing the messages to be
57 // extracted from a core dump.
59 // The text written during a process crash (following "panic" or "fatal
60 // error") is not saved, since the goroutine stacks will generally be readable
61 // from the runtime datastructures in the core file.
62 func recordForPanic(b
[]byte) {
65 if atomic
.Load(&panicking
) == 0 {
66 // Not actively crashing: maintain circular buffer of print output.
67 for i
:= 0; i
< len(b
); {
68 n
:= copy(printBacklog
[printBacklogIndex
:], b
[i
:])
70 printBacklogIndex
+= n
71 printBacklogIndex
%= len(printBacklog
)
80 // The compiler emits calls to printlock and printunlock around
81 // the multiple calls that implement a single Go print or println
82 // statement. Some of the print helpers (printslice, for example)
83 // call print recursively. There is also the problem of a crash
84 // happening during the print routines and needing to acquire
85 // the print lock to print information about the crash.
86 // For both these reasons, let a thread acquire the printlock 'recursively'.
90 mp
.locks
++ // do not reschedule between printlock++ and lock(&debuglock).
92 if mp
.printlock
== 1 {
95 mp
.locks
-- // now we know debuglock is held and holding up mp.locks for us.
101 if mp
.printlock
== 0 {
106 // write to goroutine-local buffer if diverting output,
107 // or else standard error.
108 func gwrite(b
[]byte) {
114 // Don't use the writebuf if gp.m is dying. We want anything
115 // written through gwrite to appear in the terminal rather
116 // than be written to in some buffer, if we're in a panicking state.
117 // Note that we can't just clear writebuf in the gp.m.dying case
118 // because a panic isn't allowed to have any write barriers.
119 if gp
== nil || gp
.writebuf
== nil || gp
.m
.dying
> 0 {
124 n
:= copy(gp
.writebuf
[len(gp
.writebuf
):cap(gp
.writebuf
)], b
)
125 gp
.writebuf
= gp
.writebuf
[:len(gp
.writebuf
)+n
]
136 func printbool(v
bool) {
144 func printfloat(v
float64) {
149 case v
+v
== v
&& v
> 0:
152 case v
+v
== v
&& v
< 0:
157 const n
= 7 // digits printed
183 for i
:= 0; i
< n
; i
++ {
193 // format +d.dddd+edd
194 for i
:= 0; i
< n
; i
++ {
196 buf
[i
+2] = byte(s
+ '0')
210 buf
[n
+4] = byte(e
/100) + '0'
211 buf
[n
+5] = byte(e
/10)%10
+ '0'
212 buf
[n
+6] = byte(e%10
) + '0'
216 func printcomplex(c complex128
) {
217 print("(", real(c
), imag(c
), "i)")
220 func printuint(v
uint64) {
223 for i
--; i
> 0; i
-- {
224 buf
[i
] = byte(v%10
+ '0')
233 func printint(v
int64) {
241 var minhexdigits
= 0 // protected by printlock
243 func printhex(v
uint64) {
244 const dig
= "0123456789abcdef"
247 for i
--; i
> 0; i
-- {
249 if v
< 16 && len(buf
)-i
>= minhexdigits
{
261 func printpointer(p unsafe
.Pointer
) {
262 printhex(uint64(uintptr(p
)))
264 func printuintptr(p
uintptr) {
268 func printstring(s
string) {
272 func printslice(s
[]byte) {
273 sp
:= (*slice
)(unsafe
.Pointer(&s
))
274 print("[", len(s
), "/", cap(s
), "]")
275 printpointer(sp
.array
)
278 func printeface(e eface
) {
279 print("(", e
._type
, ",", e
.data
, ")")
282 func printiface(i iface
) {
283 print("(", i
.tab
, ",", i
.data
, ")")
286 // hexdumpWords prints a word-oriented hex dump of [p, end).
288 // If mark != nil, it will be called with each printed word's address
289 // and should return a character mark to appear just before that
290 // word's value. It can return 0 to indicate no mark.
291 func hexdumpWords(p
, end
uintptr, mark
func(uintptr) byte) {
295 minhexdigits
= int(unsafe
.Sizeof(uintptr(0)) * 2)
296 for i
:= uintptr(0); p
+i
< end
; i
+= goarch
.PtrSize
{
301 print(hex(p
+i
), ": ")
305 markbuf
[0] = mark(p
+ i
)
311 val
:= *(*uintptr)(unsafe
.Pointer(p
+ i
))
315 // Can we symbolize val?
316 name
, _
, _
, _
:= funcfileline(val
, -1, false)
318 entry
:= funcentry(val
)
319 print("<", name
, "+", hex(val
-entry
), "> ")