]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: crash the GC when clobberdead pointer is seen
authorCherry Zhang <cherryyz@google.com>
Thu, 15 Apr 2021 03:38:10 +0000 (23:38 -0400)
committerCherry Zhang <cherryyz@google.com>
Tue, 20 Apr 2021 01:47:04 +0000 (01:47 +0000)
When -clobberdead compiler flag is set, the compiler inserts
instructions that set dead slots a specific value. If the GC sees
this value as a live pointer, something is probably wrong. Crash.

Only do this on AMD64 for now, as it is the only platform where
compiler's clobberdead mode is implemented. And on AMD64 the
clobberdead address can never be a valid address.

Change-Id: Ica687b132b5d3ba2a062500d13264fa730405d11
Reviewed-on: https://go-review.googlesource.com/c/go/+/310330
Trust: Cherry Zhang <cherryyz@google.com>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
src/runtime/mbitmap.go

index 2d12c563b8d15d6da3f8b036312fe0806e8a5a37..32b8db7a50282c70785615902af017232280bc35 100644 (file)
@@ -333,6 +333,10 @@ func heapBitsForAddr(addr uintptr) (h heapBits) {
        return
 }
 
+// clobberdeadPtr is a special value that is used by the compiler to
+// clobber dead stack slots, when -clobberdead flag is set.
+const clobberdeadPtr = uintptr(0xdeaddead | 0xdeaddead<<((^uintptr(0)>>63)*32))
+
 // badPointer throws bad pointer in heap panic.
 func badPointer(s *mspan, p, refBase, refOff uintptr) {
        // Typically this indicates an incorrect use
@@ -345,13 +349,16 @@ func badPointer(s *mspan, p, refBase, refOff uintptr) {
        // in allocated spans.
        printlock()
        print("runtime: pointer ", hex(p))
-       state := s.state.get()
-       if state != mSpanInUse {
-               print(" to unallocated span")
-       } else {
-               print(" to unused region of span")
+       if s != nil {
+               state := s.state.get()
+               if state != mSpanInUse {
+                       print(" to unallocated span")
+               } else {
+                       print(" to unused region of span")
+               }
+               print(" span.base()=", hex(s.base()), " span.limit=", hex(s.limit), " span.state=", state)
        }
-       print(" span.base()=", hex(s.base()), " span.limit=", hex(s.limit), " span.state=", state, "\n")
+       print("\n")
        if refBase != 0 {
                print("runtime: found in object at *(", hex(refBase), "+", hex(refOff), ")\n")
                gcDumpObject("object", refBase, refOff)
@@ -379,6 +386,12 @@ func findObject(p, refBase, refOff uintptr) (base uintptr, s *mspan, objIndex ui
        // If s is nil, the virtual address has never been part of the heap.
        // This pointer may be to some mmap'd region, so we allow it.
        if s == nil {
+               if GOARCH == "amd64" && p == clobberdeadPtr && debug.invalidptr != 0 {
+                       // Crash if clobberdeadPtr is seen. Only on AMD64 for now, as
+                       // it is the only platform where compiler's clobberdead mode is
+                       // implemented. On AMD64 clobberdeadPtr cannot be a valid address.
+                       badPointer(s, p, refBase, refOff)
+               }
                return
        }
        // If p is a bad pointer, it may not be in s's bounds.