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
+ })
+}