1
0
mirror of https://github.com/golang/go synced 2024-07-08 20:29:48 +00:00

runtime: crash the GC when clobberdead pointer is seen

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>
This commit is contained in:
Cherry Zhang 2021-04-14 23:38:10 -04:00
parent 4f5aec4603
commit 0ccdcb2102

View 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.