internal/gocore: fix IsPtr method It should look up by word index, not byte index, and it needs a &1 mask also. Change-Id: Id4b25b120b8b043184e53d70450a5f0b6b197c37 Reviewed-on: https://go-review.googlesource.com/c/debug/+/689375 Reviewed-by: Keith Randall <khr@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Michael Knyszek <mknyszek@google.com>
diff --git a/internal/gocore/gocore_test.go b/internal/gocore/gocore_test.go index 9a5981b..268fbd7 100644 --- a/internal/gocore/gocore_test.go +++ b/internal/gocore/gocore_test.go
@@ -370,6 +370,38 @@ }) } +func TestGlobals(t *testing.T) { + t.Run("goroot", func(t *testing.T) { + for _, test := range variations { + t.Run(test.String(), func(t *testing.T) { + t.Run("globals.go", func(t *testing.T) { + p := createAndLoadCore(t, "testdata/testprogs/globals.go", test.buildFlags, test.env) + for _, g := range p.Globals() { + var want []bool + switch g.Name { + default: + continue + case "main.string_": + want = []bool{true, false} + case "main.slice": + want = []bool{true, false, false} + case "main.struct_": + want = []bool{false, false, false, true, false, true, false, false} + } + a := g.Addr() + for i, wantPtr := range want { + gotPtr := p.IsPtr(a.Add(int64(i) * p.Process().PtrSize())) + if gotPtr != wantPtr { + t.Errorf("IsPtr(%s+%d)=%v, want %v", g.Name, int64(i)*p.Process().PtrSize(), gotPtr, wantPtr) + } + } + } + }) + }) + } + }) +} + // typeName returns a string representing the type of this object. func typeName(c *Process, x Object) string { size := c.Size(x)
diff --git a/internal/gocore/object.go b/internal/gocore/object.go index 8218d7a..fa85a85 100644 --- a/internal/gocore/object.go +++ b/internal/gocore/object.go
@@ -129,8 +129,8 @@ continue } gc := m.r.Field("gc" + s + "mask").Field("bytedata").Address() - i := a.Sub(min) - return p.proc.ReadUint8(gc.Add(i/8))>>uint(i%8) != 0 + i := a.Sub(min) / p.proc.PtrSize() + return p.proc.ReadUint8(gc.Add(i/8))>>uint(i%8)&1 != 0 } } // Everywhere else can't be a pointer. At least, not a pointer into the Go heap.
diff --git a/internal/gocore/testdata/testprogs/globals.go b/internal/gocore/testdata/testprogs/globals.go new file mode 100644 index 0000000..d163326 --- /dev/null +++ b/internal/gocore/testdata/testprogs/globals.go
@@ -0,0 +1,36 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build ignore + +// Tests to make sure we can tell which globals have pointers. + +package main + +import ( + "os" + "unsafe" + + "golang.org/x/debug/internal/testenv" +) + +var string_ string = "foo" // string type, in data section +var slice []byte // slice type, in bss section +var struct_ struct { // a more complicated layout + a, b, c uintptr + d *byte + e uintptr + f unsafe.Pointer + g, h uintptr +} + +func main() { + testenv.RunThenCrash(os.Getenv("GO_DEBUG_TEST_COREDUMP_FILTER"), func() any { + // Reference globals so they don't get deadcoded. + string_ = "bar" + slice = []byte{1, 2, 3} + struct_.a = 3 + return nil + }) +}