// write copies the argument buffer to memory starting at address p. // Its boolean return tells whether it succeeded. If it fails, no bytes were copied. func write(p uintptr, buf []byte) (ok bool) { defer catchFault(&ok) defer debug.SetPanicOnFault(debug.SetPanicOnFault(true)) for i := range buf { *(*byte)(unsafe.Pointer(p)) = buf[i] p++ } return true }
func TestSetPanicOnFault(t *testing.T) { old := debug.SetPanicOnFault(true) defer debug.SetPanicOnFault(old) nfault := 0 for _, addr := range faultAddrs { testSetPanicOnFault(t, uintptr(addr), &nfault) } if nfault == 0 { t.Fatalf("none of the addresses faulted") } }
// validWrite reports whether a write of the specified size can be done at address p. // TODO: It does this by actually doing a write and seeing if it succeeds. Do better. func validWrite(p uintptr, size int) (ok bool) { // Check for negative size and for (p + size) overflow. if size < 0 || uint64(^uintptr(0)-p) < uint64(size) { return false } defer catchFault(&ok) defer debug.SetPanicOnFault(debug.SetPanicOnFault(true)) ep := p + uintptr(size) for p < ep { *(*byte)(unsafe.Pointer(p)) = *(*byte)(unsafe.Pointer(p)) p++ } return true }
func TestSetPanicOnFault(t *testing.T) { // This currently results in a fault in the signal trampoline on // dragonfly/386 - see issue 7421. if GOOS == "dragonfly" && GOARCH == "386" { t.Skip("skipping test on dragonfly/386") } old := debug.SetPanicOnFault(true) defer debug.SetPanicOnFault(old) for _, addr := range faultAddrs { testSetPanicOnFault(t, uintptr(addr)) } }
func TestSetPanicOnFault(t *testing.T) { old := debug.SetPanicOnFault(true) defer debug.SetPanicOnFault(old) defer func() { if err := recover(); err == nil { t.Fatalf("did not find error in recover") } }() var p *int p = (*int)(unsafe.Pointer(^uintptr(0))) println(*p) t.Fatalf("still here - should have faulted") }
func main() { // Turn the eventual fault into a panic, not a program crash, // so that memcopy can recover. debug.SetPanicOnFault(true) size := syscall.Getpagesize() // Map 16 pages of data with a 4-page hole in the middle. data, err := syscall.Mmap(-1, 0, 16*size, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANON|syscall.MAP_PRIVATE) if err != nil { log.Fatalf("mmap: %v", err) } // Note: Cannot call syscall.Munmap, because Munmap checks // that you are unmapping a whole region returned by Mmap. // We are trying to unmap just a hole in the middle. if _, _, err := syscall.Syscall(syscall.SYS_MUNMAP, uintptr(unsafe.Pointer(&data[8*size])), uintptr(4*size), 0); err != 0 { log.Fatalf("munmap: %v", err) } other := make([]byte, 16*size) // Check that memcopy returns the actual amount copied // before the fault (8*size - 5, the offset we skip in the argument). n, err := memcopy(data[5:], other) if err == nil { log.Fatal("no error from memcopy across memory hole") } if n != 8*size-5 { log.Fatal("memcopy returned %d, want %d", n, 8*size-5) } }
func TestSetPanicOnFault(t *testing.T) { // This currently results in a fault in the signal trampoline on // dragonfly/386 - see issue 7421. if GOOS == "dragonfly" && GOARCH == "386" { t.Skip("skipping test on dragonfly/386") } old := debug.SetPanicOnFault(true) defer debug.SetPanicOnFault(old) for _, addr := range faultAddrs { if Compiler == "gccgo" && GOARCH == "386" && (addr&0xff000000) != 0 { // On gccgo these addresses can be used for // the thread stack. continue } testSetPanicOnFault(t, uintptr(addr)) } }
func TestSetPanicOnFault(t *testing.T) { t.Skip("skipping for llgo due to lack of non-call exception support") // This currently results in a fault in the signal trampoline on // dragonfly/386 - see issue 7421. if GOOS == "dragonfly" && GOARCH == "386" { t.Skip("skipping test on dragonfly/386") } old := debug.SetPanicOnFault(true) defer debug.SetPanicOnFault(old) nfault := 0 for _, addr := range faultAddrs { testSetPanicOnFault(t, uintptr(addr), &nfault) } if nfault == 0 { t.Fatalf("none of the addresses faulted") } }
func TestSetPanicOnFault(t *testing.T) { // This currently results in a fault in the signal trampoline on // dragonfly/386 - see issue 7421. if GOOS == "dragonfly" && GOARCH == "386" { t.Skip("skipping test on dragonfly/386") } old := debug.SetPanicOnFault(true) defer debug.SetPanicOnFault(old) defer func() { if err := recover(); err == nil { t.Fatalf("did not find error in recover") } }() var p *int p = (*int)(unsafe.Pointer(^uintptr(0))) println(*p) t.Fatalf("still here - should have faulted") }
func main() { debug.SetPanicOnFault(true) defer func() { if err := recover(); err == nil { panic("not panicking") } pc, _, _, _ := runtime.Caller(10) f := runtime.FuncForPC(pc) if f == nil || f.Name() != "main.f" { if f == nil { println("no func for ", unsafe.Pointer(pc)) } else { println("found func:", f.Name()) } panic("cannot find main.f on stack") } }() f(20) }