Source File
cgocheck.go
Belonging Package
runtime
// Copyright 2015 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.// Code to check that pointer writes follow the cgo rules.// These functions are invoked when GOEXPERIMENT=cgocheck2 is enabled.package runtimeimport ()const cgoWriteBarrierFail = "unpinned Go pointer stored into non-Go memory"// cgoCheckPtrWrite is called whenever a pointer is stored into memory.// It throws if the program is storing an unpinned Go pointer into non-Go// memory.//// This is called from generated code when GOEXPERIMENT=cgocheck2 is enabled.////go:nosplit//go:nowritebarrierfunc ( *unsafe.Pointer, unsafe.Pointer) {if !mainStarted {// Something early in startup hates this function.// Don't start doing any actual checking until the// runtime has set itself up.return}if !cgoIsGoPointer() {return}if cgoIsGoPointer(unsafe.Pointer()) {return}// If we are running on the system stack then dst might be an// address on the stack, which is OK.:= getg()if == .m.g0 || == .m.gsignal {return}// Allocating memory can write to various mfixalloc structs// that look like they are non-Go memory.if .m.mallocing != 0 {return}// If the object is pinned, it's safe to store it in C memory. The GC// ensures it will not be moved or freed.if isPinned() {return}// It's OK if writing to memory allocated by persistentalloc.// Do this check last because it is more expensive and rarely true.// If it is false the expense doesn't matter since we are crashing.if inPersistentAlloc(uintptr(unsafe.Pointer())) {return}systemstack(func() {println("write of unpinned Go pointer", hex(uintptr()), "to non-Go memory", hex(uintptr(unsafe.Pointer())))throw(cgoWriteBarrierFail)})}// cgoCheckMemmove is called when moving a block of memory.// It throws if the program is copying a block that contains an unpinned Go// pointer into non-Go memory.//// This is called from generated code when GOEXPERIMENT=cgocheck2 is enabled.////go:nosplit//go:nowritebarrierfunc ( *_type, , unsafe.Pointer) {cgoCheckMemmove2(, , , 0, .Size_)}// cgoCheckMemmove2 is called when moving a block of memory.// dst and src point off bytes into the value to copy.// size is the number of bytes to copy.// It throws if the program is copying a block that contains an unpinned Go// pointer into non-Go memory.////go:nosplit//go:nowritebarrierfunc ( *_type, , unsafe.Pointer, , uintptr) {if !.Pointers() {return}if !cgoIsGoPointer() {return}if cgoIsGoPointer() {return}cgoCheckTypedBlock(, , , )}// cgoCheckSliceCopy is called when copying n elements of a slice.// src and dst are pointers to the first element of the slice.// typ is the element type of the slice.// It throws if the program is copying slice elements that contain unpinned Go// pointers into non-Go memory.////go:nosplit//go:nowritebarrierfunc ( *_type, , unsafe.Pointer, int) {if !.Pointers() {return}if !cgoIsGoPointer() {return}if cgoIsGoPointer() {return}:=for := 0; < ; ++ {cgoCheckTypedBlock(, , 0, .Size_)= add(, .Size_)}}// cgoCheckTypedBlock checks the block of memory at src, for up to size bytes,// and throws if it finds an unpinned Go pointer. The type of the memory is typ,// and src is off bytes into that type.////go:nosplit//go:nowritebarrierfunc ( *_type, unsafe.Pointer, , uintptr) {// Anything past typ.PtrBytes is not a pointer.if .PtrBytes <= {return}if := .PtrBytes - ; > {=}cgoCheckBits(, getGCMask(), , )}// cgoCheckBits checks the block of memory at src, for up to size// bytes, and throws if it finds an unpinned Go pointer. The gcbits mark each// pointer value. The src pointer is off bytes into the gcbits.////go:nosplit//go:nowritebarrierfunc ( unsafe.Pointer, *byte, , uintptr) {:= / goarch.PtrSize / 8:= * goarch.PtrSize * 8:= addb(, )= add(, )-=+=var uint32for := uintptr(0); < ; += goarch.PtrSize {if &(goarch.PtrSize*8-1) == 0 {= uint32(*)= addb(, 1)} else {>>= 1}if > 0 {-= goarch.PtrSize} else {if &1 != 0 {:= *(*unsafe.Pointer)(add(, ))if cgoIsGoPointer() && !isPinned() {throw(cgoWriteBarrierFail)}}}}}// cgoCheckUsingType is like cgoCheckTypedBlock, but is a last ditch// fall back to look for pointers in src using the type information.// We only use this when looking at a value on the stack when the type// uses a GC program, because otherwise it's more efficient to use the// GC bits. This is called on the system stack.////go:nowritebarrier//go:systemstackfunc ( *_type, unsafe.Pointer, , uintptr) {if !.Pointers() {return}// Anything past typ.PtrBytes is not a pointer.if .PtrBytes <= {return}if := .PtrBytes - ; > {=}cgoCheckBits(, getGCMask(), , )}
The pages are generated with Golds v0.7.6. (GOOS=linux GOARCH=amd64)