mirror of
https://github.com/golang/go
synced 2024-11-27 04:21:24 -07:00
runtime: repair slice, string, and channel printing in gdb
"Something" changed the names of types in gdb, causing the pretty-printer matchers to fail to match. This tracks that change. Updated runtime-gdb_test.go to include a slice and a channel printing test. (The straightforward printing of a slicevar doesn't work because of compiler DWARF problems describing the slicevar, not gdb problems). Change-Id: I21607a955b9c894f11ecf3763aea2a6dd59a3f42 Reviewed-on: https://go-review.googlesource.com/c/go/+/235926 Run-TryBot: David Chase <drchase@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
parent
1193958d6b
commit
ee776b4126
@ -18,6 +18,7 @@ path to this file based on the path to the runtime package.
|
||||
from __future__ import print_function
|
||||
import re
|
||||
import sys
|
||||
import gdb
|
||||
|
||||
print("Loading Go Runtime support.", file=sys.stderr)
|
||||
#http://python3porting.com/differences.html
|
||||
@ -27,6 +28,12 @@ if sys.version > '3':
|
||||
goobjfile = gdb.current_objfile() or gdb.objfiles()[0]
|
||||
goobjfile.pretty_printers = []
|
||||
|
||||
# Older gdb renders some types differently.
|
||||
def oldnew(old, new):
|
||||
if (gdb.VERSION[0] == '7'):
|
||||
return old
|
||||
return new
|
||||
|
||||
# G state (runtime2.go)
|
||||
|
||||
def read_runtime_const(varname, default):
|
||||
@ -102,7 +109,7 @@ class SliceValue:
|
||||
class StringTypePrinter:
|
||||
"Pretty print Go strings."
|
||||
|
||||
pattern = re.compile(r'^struct string( \*)?$')
|
||||
pattern = re.compile(oldnew(r'^struct string( \*)?$',r'^string$'))
|
||||
|
||||
def __init__(self, val):
|
||||
self.val = val
|
||||
@ -118,7 +125,7 @@ class StringTypePrinter:
|
||||
class SliceTypePrinter:
|
||||
"Pretty print slices."
|
||||
|
||||
pattern = re.compile(r'^struct \[\]')
|
||||
pattern = re.compile(oldnew(r'^struct \[\]',r'^\[\]'))
|
||||
|
||||
def __init__(self, val):
|
||||
self.val = val
|
||||
@ -127,7 +134,7 @@ class SliceTypePrinter:
|
||||
return 'array'
|
||||
|
||||
def to_string(self):
|
||||
return str(self.val.type)[6:] # skip 'struct '
|
||||
return str(self.val.type)[oldnew(6,0):] # skip 'struct ' for old gdb
|
||||
|
||||
def children(self):
|
||||
sval = SliceValue(self.val)
|
||||
@ -195,7 +202,7 @@ class ChanTypePrinter:
|
||||
to inspect their contents with this pretty printer.
|
||||
"""
|
||||
|
||||
pattern = re.compile(r'^struct hchan<.*>$')
|
||||
pattern = re.compile(oldnew(r'^struct hchan<.*>$',r'^chan '))
|
||||
|
||||
def __init__(self, val):
|
||||
self.val = val
|
||||
@ -209,7 +216,7 @@ class ChanTypePrinter:
|
||||
def children(self):
|
||||
# see chan.c chanbuf(). et is the type stolen from hchan<T>::recvq->first->elem
|
||||
et = [x.type for x in self.val['recvq']['first'].type.target().fields() if x.name == 'elem'][0]
|
||||
ptr = (self.val.address + 1).cast(et.pointer())
|
||||
ptr = (self.val.address["buf"]).cast(et)
|
||||
for i in range(self.val["qcount"]):
|
||||
j = (self.val["recvx"] + i) % self.val["dataqsiz"]
|
||||
yield ('[{0}]'.format(i), (ptr + j).dereference())
|
||||
@ -229,8 +236,6 @@ def makematcher(klass):
|
||||
return matcher
|
||||
|
||||
goobjfile.pretty_printers.extend([makematcher(var) for var in vars().values() if hasattr(var, 'pattern')])
|
||||
|
||||
|
||||
#
|
||||
# Utilities
|
||||
#
|
||||
|
@ -55,7 +55,9 @@ func checkGdbEnvironment(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func checkGdbVersion(t *testing.T) {
|
||||
// checkGdbVersion ensures gdb version is supported, and returns major version
|
||||
// to allow testing conditional on gdb version.
|
||||
func checkGdbVersion(t *testing.T) int {
|
||||
// Issue 11214 reports various failures with older versions of gdb.
|
||||
out, err := exec.Command("gdb", "--version").CombinedOutput()
|
||||
if err != nil {
|
||||
@ -75,6 +77,7 @@ func checkGdbVersion(t *testing.T) {
|
||||
t.Skipf("skipping: gdb version %d.%d too old", major, minor)
|
||||
}
|
||||
t.Logf("gdb version %d.%d", major, minor)
|
||||
return major
|
||||
}
|
||||
|
||||
func checkGdbPython(t *testing.T) {
|
||||
@ -115,8 +118,17 @@ import "runtime"
|
||||
var gslice []string
|
||||
func main() {
|
||||
mapvar := make(map[string]string, 13)
|
||||
slicemap := make(map[string][]string,11)
|
||||
chanint := make(chan int, 10)
|
||||
chanstr := make(chan string, 10)
|
||||
chanint <- 99
|
||||
chanint <- 11
|
||||
chanstr <- "spongepants"
|
||||
chanstr <- "squarebob"
|
||||
mapvar["abc"] = "def"
|
||||
mapvar["ghi"] = "jkl"
|
||||
slicemap["a"] = []string{"b","c","d"}
|
||||
slicemap["e"] = []string{"f","g","h"}
|
||||
strvar := "abc"
|
||||
ptrvar := &strvar
|
||||
slicevar := make([]string, 0, 16)
|
||||
@ -125,6 +137,7 @@ func main() {
|
||||
runtime.KeepAlive(ptrvar)
|
||||
_ = ptrvar // set breakpoint here
|
||||
gslice = slicevar
|
||||
fmt.Printf("%v, %v, %v\n", slicemap, <-chanint, <-chanstr)
|
||||
runtime.KeepAlive(mapvar)
|
||||
} // END_OF_PROGRAM
|
||||
`
|
||||
@ -157,7 +170,7 @@ func testGdbPython(t *testing.T, cgo bool) {
|
||||
|
||||
checkGdbEnvironment(t)
|
||||
t.Parallel()
|
||||
checkGdbVersion(t)
|
||||
gdbMajor := checkGdbVersion(t)
|
||||
checkGdbPython(t)
|
||||
|
||||
dir, err := ioutil.TempDir("", "go-build")
|
||||
@ -227,9 +240,18 @@ func testGdbPython(t *testing.T, cgo bool) {
|
||||
"-ex", "echo BEGIN print mapvar\n",
|
||||
"-ex", "print mapvar",
|
||||
"-ex", "echo END\n",
|
||||
"-ex", "echo BEGIN print slicemap\n",
|
||||
"-ex", "print slicemap",
|
||||
"-ex", "echo END\n",
|
||||
"-ex", "echo BEGIN print strvar\n",
|
||||
"-ex", "print strvar",
|
||||
"-ex", "echo END\n",
|
||||
"-ex", "echo BEGIN print chanint\n",
|
||||
"-ex", "print chanint",
|
||||
"-ex", "echo END\n",
|
||||
"-ex", "echo BEGIN print chanstr\n",
|
||||
"-ex", "print chanstr",
|
||||
"-ex", "echo END\n",
|
||||
"-ex", "echo BEGIN info locals\n",
|
||||
"-ex", "info locals",
|
||||
"-ex", "echo END\n",
|
||||
@ -290,6 +312,25 @@ func testGdbPython(t *testing.T, cgo bool) {
|
||||
t.Fatalf("print mapvar failed: %s", bl)
|
||||
}
|
||||
|
||||
// 2 orders, and possible differences in spacing.
|
||||
sliceMapSfx1 := `map[string][]string = {["e"] = []string = {"f", "g", "h"}, ["a"] = []string = {"b", "c", "d"}}`
|
||||
sliceMapSfx2 := `map[string][]string = {["a"] = []string = {"b", "c", "d"}, ["e"] = []string = {"f", "g", "h"}}`
|
||||
if bl := strings.ReplaceAll(blocks["print slicemap"], " ", " "); !strings.HasSuffix(bl, sliceMapSfx1) && !strings.HasSuffix(bl, sliceMapSfx2) {
|
||||
t.Fatalf("print slicemap failed: %s", bl)
|
||||
}
|
||||
|
||||
if gdbMajor > 7 {
|
||||
chanIntSfx := `chan int = {99, 11}`
|
||||
if bl := strings.ReplaceAll(blocks["print chanint"], " ", " "); !strings.HasSuffix(bl, chanIntSfx) {
|
||||
t.Fatalf("print chanint failed: %s", bl)
|
||||
}
|
||||
|
||||
chanStrSfx := `chan string = {"spongepants", "squarebob"}`
|
||||
if bl := strings.ReplaceAll(blocks["print chanstr"], " ", " "); !strings.HasSuffix(bl, chanStrSfx) {
|
||||
t.Fatalf("print chanstr failed: %s", bl)
|
||||
}
|
||||
}
|
||||
|
||||
strVarRe := regexp.MustCompile(`^\$[0-9]+ = (0x[0-9a-f]+\s+)?"abc"$`)
|
||||
if bl := blocks["print strvar"]; !strVarRe.MatchString(bl) {
|
||||
t.Fatalf("print strvar failed: %s", bl)
|
||||
@ -366,7 +407,7 @@ func TestGdbBacktrace(t *testing.T) {
|
||||
|
||||
checkGdbEnvironment(t)
|
||||
t.Parallel()
|
||||
checkGdbVersion(t)
|
||||
_ = checkGdbVersion(t)
|
||||
|
||||
dir, err := ioutil.TempDir("", "go-build")
|
||||
if err != nil {
|
||||
@ -440,7 +481,7 @@ func main() {
|
||||
func TestGdbAutotmpTypes(t *testing.T) {
|
||||
checkGdbEnvironment(t)
|
||||
t.Parallel()
|
||||
checkGdbVersion(t)
|
||||
_ = checkGdbVersion(t)
|
||||
|
||||
if runtime.GOOS == "aix" && testing.Short() {
|
||||
t.Skip("TestGdbAutotmpTypes is too slow on aix/ppc64")
|
||||
@ -513,7 +554,7 @@ func main() {
|
||||
func TestGdbConst(t *testing.T) {
|
||||
checkGdbEnvironment(t)
|
||||
t.Parallel()
|
||||
checkGdbVersion(t)
|
||||
_ = checkGdbVersion(t)
|
||||
|
||||
dir, err := ioutil.TempDir("", "go-build")
|
||||
if err != nil {
|
||||
@ -580,7 +621,7 @@ func crash() {
|
||||
func TestGdbPanic(t *testing.T) {
|
||||
checkGdbEnvironment(t)
|
||||
t.Parallel()
|
||||
checkGdbVersion(t)
|
||||
_ = checkGdbVersion(t)
|
||||
|
||||
dir, err := ioutil.TempDir("", "go-build")
|
||||
if err != nil {
|
||||
@ -658,7 +699,7 @@ func TestGdbInfCallstack(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Parallel()
|
||||
checkGdbVersion(t)
|
||||
_ = checkGdbVersion(t)
|
||||
|
||||
dir, err := ioutil.TempDir("", "go-build")
|
||||
if err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user