aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/print.go
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2018-01-22 14:53:36 -0500
committerAustin Clements <austin@google.com>2018-01-22 21:51:29 +0000
commitdbd8f3d739fe4ec34dd48f655edc15443c23a580 (patch)
treec69d3eee4e19a67bf3a007115c0481de5a27e625 /src/runtime/print.go
parent2923b209b39014b07ece2c73b339af3a5dbc0fc8 (diff)
downloadgo-dbd8f3d739fe4ec34dd48f655edc15443c23a580.tar.gz
go-dbd8f3d739fe4ec34dd48f655edc15443c23a580.zip
runtime: print hexdump on traceback failure
Currently, if anything goes wrong when printing a traceback, we simply cut off the traceback without any further diagnostics. Unfortunately, right now, we have a few issues that are difficult to debug because the traceback simply cuts off (#21431, #23484). This is an attempt to improve the debuggability of traceback failure by printing a diagnostic message plus a hex dump around the failed traceback frame when something goes wrong. The failures look like: goroutine 5 [running]: runtime: unexpected return pc for main.badLR2 called from 0xbad stack: frame={sp:0xc42004dfa8, fp:0xc42004dfc8} stack=[0xc42004d800,0xc42004e000) 000000c42004dea8: 0000000000000001 0000000000000001 000000c42004deb8: 000000c42004ded8 000000c42004ded8 000000c42004dec8: 0000000000427eea <runtime.dopanic+74> 000000c42004ded8 000000c42004ded8: 000000000044df70 <runtime.dopanic.func1+0> 000000c420001080 000000c42004dee8: 0000000000427b21 <runtime.gopanic+961> 000000c42004df08 000000c42004def8: 000000c42004df98 0000000000427b21 <runtime.gopanic+961> 000000c42004df08: 0000000000000000 0000000000000000 000000c42004df18: 0000000000000000 0000000000000000 000000c42004df28: 0000000000000000 0000000000000000 000000c42004df38: 0000000000000000 000000c420001080 000000c42004df48: 0000000000000000 0000000000000000 000000c42004df58: 0000000000000000 0000000000000000 000000c42004df68: 000000c4200010a0 0000000000000000 000000c42004df78: 00000000004c6400 00000000005031d0 000000c42004df88: 0000000000000000 0000000000000000 000000c42004df98: 000000c42004dfb8 00000000004ae7d9 <main.badLR2+73> 000000c42004dfa8: <00000000004c6400 00000000005031d0 000000c42004dfb8: 000000c42004dfd0 !0000000000000bad 000000c42004dfc8: >0000000000000000 0000000000000000 000000c42004dfd8: 0000000000451821 <runtime.goexit+1> 0000000000000000 000000c42004dfe8: 0000000000000000 0000000000000000 000000c42004dff8: 0000000000000000 main.badLR2(0x0) /go/src/runtime/testdata/testprog/badtraceback.go:42 +0x49 For #21431, #23484. Change-Id: I8718fc76ced81adb0b4b0b4f2293f3219ca80786 Reviewed-on: https://go-review.googlesource.com/89016 Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
Diffstat (limited to 'src/runtime/print.go')
-rw-r--r--src/runtime/print.go53
1 files changed, 53 insertions, 0 deletions
diff --git a/src/runtime/print.go b/src/runtime/print.go
index a698fcb0e0..7b2e4f40ff 100644
--- a/src/runtime/print.go
+++ b/src/runtime/print.go
@@ -6,6 +6,7 @@ package runtime
import (
"runtime/internal/atomic"
+ "runtime/internal/sys"
"unsafe"
)
@@ -249,3 +250,55 @@ func printeface(e eface) {
func printiface(i iface) {
print("(", i.tab, ",", i.data, ")")
}
+
+// hexdumpWords prints a word-oriented hex dump of [p, end).
+//
+// If mark != nil, it will be called with each printed word's address
+// and should return a character mark to appear just before that
+// word's value. It can return 0 to indicate no mark.
+func hexdumpWords(p, end uintptr, mark func(uintptr) byte) {
+ p1 := func(x uintptr) {
+ var buf [2 * sys.PtrSize]byte
+ for i := len(buf) - 1; i >= 0; i-- {
+ if x&0xF < 10 {
+ buf[i] = byte(x&0xF) + '0'
+ } else {
+ buf[i] = byte(x&0xF) - 10 + 'a'
+ }
+ x >>= 4
+ }
+ gwrite(buf[:])
+ }
+
+ printlock()
+ var markbuf [1]byte
+ markbuf[0] = ' '
+ for i := uintptr(0); p+i < end; i += sys.PtrSize {
+ if i%16 == 0 {
+ if i != 0 {
+ println()
+ }
+ p1(p + i)
+ print(": ")
+ }
+
+ if mark != nil {
+ markbuf[0] = mark(p + i)
+ if markbuf[0] == 0 {
+ markbuf[0] = ' '
+ }
+ }
+ gwrite(markbuf[:])
+ val := *(*uintptr)(unsafe.Pointer(p + i))
+ p1(val)
+ print(" ")
+
+ // Can we symbolize val?
+ fn := findfunc(val)
+ if fn.valid() {
+ print("<", funcname(fn), "+", val-fn.entry, "> ")
+ }
+ }
+ println()
+ printunlock()
+}