Home | History | Annotate | Download | only in runtime
      1 // Copyright 2009 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // Cgo call and callback support.
      6 //
      7 // To call into the C function f from Go, the cgo-generated code calls
      8 // runtime.cgocall(_cgo_Cfunc_f, frame), where _cgo_Cfunc_f is a
      9 // gcc-compiled function written by cgo.
     10 //
     11 // runtime.cgocall (below) calls entersyscall so as not to block
     12 // other goroutines or the garbage collector, and then calls
     13 // runtime.asmcgocall(_cgo_Cfunc_f, frame).
     14 //
     15 // runtime.asmcgocall (in asm_$GOARCH.s) switches to the m->g0 stack
     16 // (assumed to be an operating system-allocated stack, so safe to run
     17 // gcc-compiled code on) and calls _cgo_Cfunc_f(frame).
     18 //
     19 // _cgo_Cfunc_f invokes the actual C function f with arguments
     20 // taken from the frame structure, records the results in the frame,
     21 // and returns to runtime.asmcgocall.
     22 //
     23 // After it regains control, runtime.asmcgocall switches back to the
     24 // original g (m->curg)'s stack and returns to runtime.cgocall.
     25 //
     26 // After it regains control, runtime.cgocall calls exitsyscall, which blocks
     27 // until this m can run Go code without violating the $GOMAXPROCS limit,
     28 // and then unlocks g from m.
     29 //
     30 // The above description skipped over the possibility of the gcc-compiled
     31 // function f calling back into Go. If that happens, we continue down
     32 // the rabbit hole during the execution of f.
     33 //
     34 // To make it possible for gcc-compiled C code to call a Go function p.GoF,
     35 // cgo writes a gcc-compiled function named GoF (not p.GoF, since gcc doesn't
     36 // know about packages).  The gcc-compiled C function f calls GoF.
     37 //
     38 // GoF calls crosscall2(_cgoexp_GoF, frame, framesize).  Crosscall2
     39 // (in cgo/gcc_$GOARCH.S, a gcc-compiled assembly file) is a two-argument
     40 // adapter from the gcc function call ABI to the 6c function call ABI.
     41 // It is called from gcc to call 6c functions. In this case it calls
     42 // _cgoexp_GoF(frame, framesize), still running on m->g0's stack
     43 // and outside the $GOMAXPROCS limit. Thus, this code cannot yet
     44 // call arbitrary Go code directly and must be careful not to allocate
     45 // memory or use up m->g0's stack.
     46 //
     47 // _cgoexp_GoF calls runtime.cgocallback(p.GoF, frame, framesize, ctxt).
     48 // (The reason for having _cgoexp_GoF instead of writing a crosscall3
     49 // to make this call directly is that _cgoexp_GoF, because it is compiled
     50 // with 6c instead of gcc, can refer to dotted names like
     51 // runtime.cgocallback and p.GoF.)
     52 //
     53 // runtime.cgocallback (in asm_$GOARCH.s) switches from m->g0's
     54 // stack to the original g (m->curg)'s stack, on which it calls
     55 // runtime.cgocallbackg(p.GoF, frame, framesize).
     56 // As part of the stack switch, runtime.cgocallback saves the current
     57 // SP as m->g0->sched.sp, so that any use of m->g0's stack during the
     58 // execution of the callback will be done below the existing stack frames.
     59 // Before overwriting m->g0->sched.sp, it pushes the old value on the
     60 // m->g0 stack, so that it can be restored later.
     61 //
     62 // runtime.cgocallbackg (below) is now running on a real goroutine
     63 // stack (not an m->g0 stack).  First it calls runtime.exitsyscall, which will
     64 // block until the $GOMAXPROCS limit allows running this goroutine.
     65 // Once exitsyscall has returned, it is safe to do things like call the memory
     66 // allocator or invoke the Go callback function p.GoF.  runtime.cgocallbackg
     67 // first defers a function to unwind m->g0.sched.sp, so that if p.GoF
     68 // panics, m->g0.sched.sp will be restored to its old value: the m->g0 stack
     69 // and the m->curg stack will be unwound in lock step.
     70 // Then it calls p.GoF.  Finally it pops but does not execute the deferred
     71 // function, calls runtime.entersyscall, and returns to runtime.cgocallback.
     72 //
     73 // After it regains control, runtime.cgocallback switches back to
     74 // m->g0's stack (the pointer is still in m->g0.sched.sp), restores the old
     75 // m->g0.sched.sp value from the stack, and returns to _cgoexp_GoF.
     76 //
     77 // _cgoexp_GoF immediately returns to crosscall2, which restores the
     78 // callee-save registers for gcc and returns to GoF, which returns to f.
     79 
     80 package runtime
     81 
     82 import (
     83 	"runtime/internal/atomic"
     84 	"runtime/internal/sys"
     85 	"unsafe"
     86 )
     87 
     88 // Addresses collected in a cgo backtrace when crashing.
     89 // Length must match arg.Max in x_cgo_callers in runtime/cgo/gcc_traceback.c.
     90 type cgoCallers [32]uintptr
     91 
     92 // Call from Go to C.
     93 //go:nosplit
     94 func cgocall(fn, arg unsafe.Pointer) int32 {
     95 	if !iscgo && GOOS != "solaris" && GOOS != "windows" {
     96 		throw("cgocall unavailable")
     97 	}
     98 
     99 	if fn == nil {
    100 		throw("cgocall nil")
    101 	}
    102 
    103 	if raceenabled {
    104 		racereleasemerge(unsafe.Pointer(&racecgosync))
    105 	}
    106 
    107 	mp := getg().m
    108 	mp.ncgocall++
    109 	mp.ncgo++
    110 
    111 	// Reset traceback.
    112 	mp.cgoCallers[0] = 0
    113 
    114 	// Announce we are entering a system call
    115 	// so that the scheduler knows to create another
    116 	// M to run goroutines while we are in the
    117 	// foreign code.
    118 	//
    119 	// The call to asmcgocall is guaranteed not to
    120 	// grow the stack and does not allocate memory,
    121 	// so it is safe to call while "in a system call", outside
    122 	// the $GOMAXPROCS accounting.
    123 	//
    124 	// fn may call back into Go code, in which case we'll exit the
    125 	// "system call", run the Go code (which may grow the stack),
    126 	// and then re-enter the "system call" reusing the PC and SP
    127 	// saved by entersyscall here.
    128 	entersyscall(0)
    129 
    130 	mp.incgo = true
    131 	errno := asmcgocall(fn, arg)
    132 
    133 	// Call endcgo before exitsyscall because exitsyscall may
    134 	// reschedule us on to a different M.
    135 	endcgo(mp)
    136 
    137 	exitsyscall(0)
    138 
    139 	// From the garbage collector's perspective, time can move
    140 	// backwards in the sequence above. If there's a callback into
    141 	// Go code, GC will see this function at the call to
    142 	// asmcgocall. When the Go call later returns to C, the
    143 	// syscall PC/SP is rolled back and the GC sees this function
    144 	// back at the call to entersyscall. Normally, fn and arg
    145 	// would be live at entersyscall and dead at asmcgocall, so if
    146 	// time moved backwards, GC would see these arguments as dead
    147 	// and then live. Prevent these undead arguments from crashing
    148 	// GC by forcing them to stay live across this time warp.
    149 	KeepAlive(fn)
    150 	KeepAlive(arg)
    151 	KeepAlive(mp)
    152 
    153 	return errno
    154 }
    155 
    156 //go:nosplit
    157 func endcgo(mp *m) {
    158 	mp.incgo = false
    159 	mp.ncgo--
    160 
    161 	if raceenabled {
    162 		raceacquire(unsafe.Pointer(&racecgosync))
    163 	}
    164 }
    165 
    166 // Call from C back to Go.
    167 //go:nosplit
    168 func cgocallbackg(ctxt uintptr) {
    169 	gp := getg()
    170 	if gp != gp.m.curg {
    171 		println("runtime: bad g in cgocallback")
    172 		exit(2)
    173 	}
    174 
    175 	// The call from C is on gp.m's g0 stack, so we must ensure
    176 	// that we stay on that M. We have to do this before calling
    177 	// exitsyscall, since it would otherwise be free to move us to
    178 	// a different M. The call to unlockOSThread is in unwindm.
    179 	lockOSThread()
    180 
    181 	// Save current syscall parameters, so m.syscall can be
    182 	// used again if callback decide to make syscall.
    183 	syscall := gp.m.syscall
    184 
    185 	// entersyscall saves the caller's SP to allow the GC to trace the Go
    186 	// stack. However, since we're returning to an earlier stack frame and
    187 	// need to pair with the entersyscall() call made by cgocall, we must
    188 	// save syscall* and let reentersyscall restore them.
    189 	savedsp := unsafe.Pointer(gp.syscallsp)
    190 	savedpc := gp.syscallpc
    191 	exitsyscall(0) // coming out of cgo call
    192 	gp.m.incgo = false
    193 
    194 	cgocallbackg1(ctxt)
    195 
    196 	// At this point unlockOSThread has been called.
    197 	// The following code must not change to a different m.
    198 	// This is enforced by checking incgo in the schedule function.
    199 
    200 	gp.m.incgo = true
    201 	// going back to cgo call
    202 	reentersyscall(savedpc, uintptr(savedsp))
    203 
    204 	gp.m.syscall = syscall
    205 }
    206 
    207 func cgocallbackg1(ctxt uintptr) {
    208 	gp := getg()
    209 	if gp.m.needextram || atomic.Load(&extraMWaiters) > 0 {
    210 		gp.m.needextram = false
    211 		systemstack(newextram)
    212 	}
    213 
    214 	if ctxt != 0 {
    215 		s := append(gp.cgoCtxt, ctxt)
    216 
    217 		// Now we need to set gp.cgoCtxt = s, but we could get
    218 		// a SIGPROF signal while manipulating the slice, and
    219 		// the SIGPROF handler could pick up gp.cgoCtxt while
    220 		// tracing up the stack.  We need to ensure that the
    221 		// handler always sees a valid slice, so set the
    222 		// values in an order such that it always does.
    223 		p := (*slice)(unsafe.Pointer(&gp.cgoCtxt))
    224 		atomicstorep(unsafe.Pointer(&p.array), unsafe.Pointer(&s[0]))
    225 		p.cap = cap(s)
    226 		p.len = len(s)
    227 
    228 		defer func(gp *g) {
    229 			// Decrease the length of the slice by one, safely.
    230 			p := (*slice)(unsafe.Pointer(&gp.cgoCtxt))
    231 			p.len--
    232 		}(gp)
    233 	}
    234 
    235 	if gp.m.ncgo == 0 {
    236 		// The C call to Go came from a thread not currently running
    237 		// any Go. In the case of -buildmode=c-archive or c-shared,
    238 		// this call may be coming in before package initialization
    239 		// is complete. Wait until it is.
    240 		<-main_init_done
    241 	}
    242 
    243 	// Add entry to defer stack in case of panic.
    244 	restore := true
    245 	defer unwindm(&restore)
    246 
    247 	if raceenabled {
    248 		raceacquire(unsafe.Pointer(&racecgosync))
    249 	}
    250 
    251 	type args struct {
    252 		fn      *funcval
    253 		arg     unsafe.Pointer
    254 		argsize uintptr
    255 	}
    256 	var cb *args
    257 
    258 	// Location of callback arguments depends on stack frame layout
    259 	// and size of stack frame of cgocallback_gofunc.
    260 	sp := gp.m.g0.sched.sp
    261 	switch GOARCH {
    262 	default:
    263 		throw("cgocallbackg is unimplemented on arch")
    264 	case "arm":
    265 		// On arm, stack frame is two words and there's a saved LR between
    266 		// SP and the stack frame and between the stack frame and the arguments.
    267 		cb = (*args)(unsafe.Pointer(sp + 4*sys.PtrSize))
    268 	case "arm64":
    269 		// On arm64, stack frame is four words and there's a saved LR between
    270 		// SP and the stack frame and between the stack frame and the arguments.
    271 		cb = (*args)(unsafe.Pointer(sp + 5*sys.PtrSize))
    272 	case "amd64":
    273 		// On amd64, stack frame is two words, plus caller PC.
    274 		if framepointer_enabled {
    275 			// In this case, there's also saved BP.
    276 			cb = (*args)(unsafe.Pointer(sp + 4*sys.PtrSize))
    277 			break
    278 		}
    279 		cb = (*args)(unsafe.Pointer(sp + 3*sys.PtrSize))
    280 	case "386":
    281 		// On 386, stack frame is three words, plus caller PC.
    282 		cb = (*args)(unsafe.Pointer(sp + 4*sys.PtrSize))
    283 	case "ppc64", "ppc64le", "s390x":
    284 		// On ppc64 and s390x, the callback arguments are in the arguments area of
    285 		// cgocallback's stack frame. The stack looks like this:
    286 		// +--------------------+------------------------------+
    287 		// |                    | ...                          |
    288 		// | cgoexp_$fn         +------------------------------+
    289 		// |                    | fixed frame area             |
    290 		// +--------------------+------------------------------+
    291 		// |                    | arguments area               |
    292 		// | cgocallback        +------------------------------+ <- sp + 2*minFrameSize + 2*ptrSize
    293 		// |                    | fixed frame area             |
    294 		// +--------------------+------------------------------+ <- sp + minFrameSize + 2*ptrSize
    295 		// |                    | local variables (2 pointers) |
    296 		// | cgocallback_gofunc +------------------------------+ <- sp + minFrameSize
    297 		// |                    | fixed frame area             |
    298 		// +--------------------+------------------------------+ <- sp
    299 		cb = (*args)(unsafe.Pointer(sp + 2*sys.MinFrameSize + 2*sys.PtrSize))
    300 	case "mips64", "mips64le":
    301 		// On mips64x, stack frame is two words and there's a saved LR between
    302 		// SP and the stack frame and between the stack frame and the arguments.
    303 		cb = (*args)(unsafe.Pointer(sp + 4*sys.PtrSize))
    304 	case "mips", "mipsle":
    305 		// On mipsx, stack frame is two words and there's a saved LR between
    306 		// SP and the stack frame and between the stack frame and the arguments.
    307 		cb = (*args)(unsafe.Pointer(sp + 4*sys.PtrSize))
    308 	}
    309 
    310 	// Invoke callback.
    311 	// NOTE(rsc): passing nil for argtype means that the copying of the
    312 	// results back into cb.arg happens without any corresponding write barriers.
    313 	// For cgo, cb.arg points into a C stack frame and therefore doesn't
    314 	// hold any pointers that the GC can find anyway - the write barrier
    315 	// would be a no-op.
    316 	reflectcall(nil, unsafe.Pointer(cb.fn), cb.arg, uint32(cb.argsize), 0)
    317 
    318 	if raceenabled {
    319 		racereleasemerge(unsafe.Pointer(&racecgosync))
    320 	}
    321 	if msanenabled {
    322 		// Tell msan that we wrote to the entire argument block.
    323 		// This tells msan that we set the results.
    324 		// Since we have already called the function it doesn't
    325 		// matter that we are writing to the non-result parameters.
    326 		msanwrite(cb.arg, cb.argsize)
    327 	}
    328 
    329 	// Do not unwind m->g0->sched.sp.
    330 	// Our caller, cgocallback, will do that.
    331 	restore = false
    332 }
    333 
    334 func unwindm(restore *bool) {
    335 	if *restore {
    336 		// Restore sp saved by cgocallback during
    337 		// unwind of g's stack (see comment at top of file).
    338 		mp := acquirem()
    339 		sched := &mp.g0.sched
    340 		switch GOARCH {
    341 		default:
    342 			throw("unwindm not implemented")
    343 		case "386", "amd64", "arm", "ppc64", "ppc64le", "mips64", "mips64le", "s390x", "mips", "mipsle":
    344 			sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + sys.MinFrameSize))
    345 		case "arm64":
    346 			sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + 16))
    347 		}
    348 
    349 		// Call endcgo to do the accounting that cgocall will not have a
    350 		// chance to do during an unwind.
    351 		//
    352 		// In the case where a Go call originates from C, ncgo is 0
    353 		// and there is no matching cgocall to end.
    354 		if mp.ncgo > 0 {
    355 			endcgo(mp)
    356 		}
    357 
    358 		releasem(mp)
    359 	}
    360 
    361 	// Undo the call to lockOSThread in cgocallbackg.
    362 	// We must still stay on the same m.
    363 	unlockOSThread()
    364 }
    365 
    366 // called from assembly
    367 func badcgocallback() {
    368 	throw("misaligned stack in cgocallback")
    369 }
    370 
    371 // called from (incomplete) assembly
    372 func cgounimpl() {
    373 	throw("cgo not implemented")
    374 }
    375 
    376 var racecgosync uint64 // represents possible synchronization in C code
    377 
    378 // Pointer checking for cgo code.
    379 
    380 // We want to detect all cases where a program that does not use
    381 // unsafe makes a cgo call passing a Go pointer to memory that
    382 // contains a Go pointer. Here a Go pointer is defined as a pointer
    383 // to memory allocated by the Go runtime. Programs that use unsafe
    384 // can evade this restriction easily, so we don't try to catch them.
    385 // The cgo program will rewrite all possibly bad pointer arguments to
    386 // call cgoCheckPointer, where we can catch cases of a Go pointer
    387 // pointing to a Go pointer.
    388 
    389 // Complicating matters, taking the address of a slice or array
    390 // element permits the C program to access all elements of the slice
    391 // or array. In that case we will see a pointer to a single element,
    392 // but we need to check the entire data structure.
    393 
    394 // The cgoCheckPointer call takes additional arguments indicating that
    395 // it was called on an address expression. An additional argument of
    396 // true means that it only needs to check a single element. An
    397 // additional argument of a slice or array means that it needs to
    398 // check the entire slice/array, but nothing else. Otherwise, the
    399 // pointer could be anything, and we check the entire heap object,
    400 // which is conservative but safe.
    401 
    402 // When and if we implement a moving garbage collector,
    403 // cgoCheckPointer will pin the pointer for the duration of the cgo
    404 // call.  (This is necessary but not sufficient; the cgo program will
    405 // also have to change to pin Go pointers that cannot point to Go
    406 // pointers.)
    407 
    408 // cgoCheckPointer checks if the argument contains a Go pointer that
    409 // points to a Go pointer, and panics if it does.
    410 func cgoCheckPointer(ptr interface{}, args ...interface{}) {
    411 	if debug.cgocheck == 0 {
    412 		return
    413 	}
    414 
    415 	ep := (*eface)(unsafe.Pointer(&ptr))
    416 	t := ep._type
    417 
    418 	top := true
    419 	if len(args) > 0 && (t.kind&kindMask == kindPtr || t.kind&kindMask == kindUnsafePointer) {
    420 		p := ep.data
    421 		if t.kind&kindDirectIface == 0 {
    422 			p = *(*unsafe.Pointer)(p)
    423 		}
    424 		if !cgoIsGoPointer(p) {
    425 			return
    426 		}
    427 		aep := (*eface)(unsafe.Pointer(&args[0]))
    428 		switch aep._type.kind & kindMask {
    429 		case kindBool:
    430 			if t.kind&kindMask == kindUnsafePointer {
    431 				// We don't know the type of the element.
    432 				break
    433 			}
    434 			pt := (*ptrtype)(unsafe.Pointer(t))
    435 			cgoCheckArg(pt.elem, p, true, false, cgoCheckPointerFail)
    436 			return
    437 		case kindSlice:
    438 			// Check the slice rather than the pointer.
    439 			ep = aep
    440 			t = ep._type
    441 		case kindArray:
    442 			// Check the array rather than the pointer.
    443 			// Pass top as false since we have a pointer
    444 			// to the array.
    445 			ep = aep
    446 			t = ep._type
    447 			top = false
    448 		default:
    449 			throw("can't happen")
    450 		}
    451 	}
    452 
    453 	cgoCheckArg(t, ep.data, t.kind&kindDirectIface == 0, top, cgoCheckPointerFail)
    454 }
    455 
    456 const cgoCheckPointerFail = "cgo argument has Go pointer to Go pointer"
    457 const cgoResultFail = "cgo result has Go pointer"
    458 
    459 // cgoCheckArg is the real work of cgoCheckPointer. The argument p
    460 // is either a pointer to the value (of type t), or the value itself,
    461 // depending on indir. The top parameter is whether we are at the top
    462 // level, where Go pointers are allowed.
    463 func cgoCheckArg(t *_type, p unsafe.Pointer, indir, top bool, msg string) {
    464 	if t.kind&kindNoPointers != 0 {
    465 		// If the type has no pointers there is nothing to do.
    466 		return
    467 	}
    468 
    469 	switch t.kind & kindMask {
    470 	default:
    471 		throw("can't happen")
    472 	case kindArray:
    473 		at := (*arraytype)(unsafe.Pointer(t))
    474 		if !indir {
    475 			if at.len != 1 {
    476 				throw("can't happen")
    477 			}
    478 			cgoCheckArg(at.elem, p, at.elem.kind&kindDirectIface == 0, top, msg)
    479 			return
    480 		}
    481 		for i := uintptr(0); i < at.len; i++ {
    482 			cgoCheckArg(at.elem, p, true, top, msg)
    483 			p = add(p, at.elem.size)
    484 		}
    485 	case kindChan, kindMap:
    486 		// These types contain internal pointers that will
    487 		// always be allocated in the Go heap. It's never OK
    488 		// to pass them to C.
    489 		panic(errorString(msg))
    490 	case kindFunc:
    491 		if indir {
    492 			p = *(*unsafe.Pointer)(p)
    493 		}
    494 		if !cgoIsGoPointer(p) {
    495 			return
    496 		}
    497 		panic(errorString(msg))
    498 	case kindInterface:
    499 		it := *(**_type)(p)
    500 		if it == nil {
    501 			return
    502 		}
    503 		// A type known at compile time is OK since it's
    504 		// constant. A type not known at compile time will be
    505 		// in the heap and will not be OK.
    506 		if inheap(uintptr(unsafe.Pointer(it))) {
    507 			panic(errorString(msg))
    508 		}
    509 		p = *(*unsafe.Pointer)(add(p, sys.PtrSize))
    510 		if !cgoIsGoPointer(p) {
    511 			return
    512 		}
    513 		if !top {
    514 			panic(errorString(msg))
    515 		}
    516 		cgoCheckArg(it, p, it.kind&kindDirectIface == 0, false, msg)
    517 	case kindSlice:
    518 		st := (*slicetype)(unsafe.Pointer(t))
    519 		s := (*slice)(p)
    520 		p = s.array
    521 		if !cgoIsGoPointer(p) {
    522 			return
    523 		}
    524 		if !top {
    525 			panic(errorString(msg))
    526 		}
    527 		if st.elem.kind&kindNoPointers != 0 {
    528 			return
    529 		}
    530 		for i := 0; i < s.cap; i++ {
    531 			cgoCheckArg(st.elem, p, true, false, msg)
    532 			p = add(p, st.elem.size)
    533 		}
    534 	case kindString:
    535 		ss := (*stringStruct)(p)
    536 		if !cgoIsGoPointer(ss.str) {
    537 			return
    538 		}
    539 		if !top {
    540 			panic(errorString(msg))
    541 		}
    542 	case kindStruct:
    543 		st := (*structtype)(unsafe.Pointer(t))
    544 		if !indir {
    545 			if len(st.fields) != 1 {
    546 				throw("can't happen")
    547 			}
    548 			cgoCheckArg(st.fields[0].typ, p, st.fields[0].typ.kind&kindDirectIface == 0, top, msg)
    549 			return
    550 		}
    551 		for _, f := range st.fields {
    552 			cgoCheckArg(f.typ, add(p, f.offset()), true, top, msg)
    553 		}
    554 	case kindPtr, kindUnsafePointer:
    555 		if indir {
    556 			p = *(*unsafe.Pointer)(p)
    557 		}
    558 
    559 		if !cgoIsGoPointer(p) {
    560 			return
    561 		}
    562 		if !top {
    563 			panic(errorString(msg))
    564 		}
    565 
    566 		cgoCheckUnknownPointer(p, msg)
    567 	}
    568 }
    569 
    570 // cgoCheckUnknownPointer is called for an arbitrary pointer into Go
    571 // memory. It checks whether that Go memory contains any other
    572 // pointer into Go memory. If it does, we panic.
    573 // The return values are unused but useful to see in panic tracebacks.
    574 func cgoCheckUnknownPointer(p unsafe.Pointer, msg string) (base, i uintptr) {
    575 	if cgoInRange(p, mheap_.arena_start, mheap_.arena_used) {
    576 		if !inheap(uintptr(p)) {
    577 			// On 32-bit systems it is possible for C's allocated memory
    578 			// to have addresses between arena_start and arena_used.
    579 			// Either this pointer is a stack or an unused span or it's
    580 			// a C allocation. Escape analysis should prevent the first,
    581 			// garbage collection should prevent the second,
    582 			// and the third is completely OK.
    583 			return
    584 		}
    585 
    586 		b, hbits, span, _ := heapBitsForObject(uintptr(p), 0, 0)
    587 		base = b
    588 		if base == 0 {
    589 			return
    590 		}
    591 		n := span.elemsize
    592 		for i = uintptr(0); i < n; i += sys.PtrSize {
    593 			if i != 1*sys.PtrSize && !hbits.morePointers() {
    594 				// No more possible pointers.
    595 				break
    596 			}
    597 			if hbits.isPointer() && cgoIsGoPointer(*(*unsafe.Pointer)(unsafe.Pointer(base + i))) {
    598 				panic(errorString(msg))
    599 			}
    600 			hbits = hbits.next()
    601 		}
    602 
    603 		return
    604 	}
    605 
    606 	for _, datap := range activeModules() {
    607 		if cgoInRange(p, datap.data, datap.edata) || cgoInRange(p, datap.bss, datap.ebss) {
    608 			// We have no way to know the size of the object.
    609 			// We have to assume that it might contain a pointer.
    610 			panic(errorString(msg))
    611 		}
    612 		// In the text or noptr sections, we know that the
    613 		// pointer does not point to a Go pointer.
    614 	}
    615 
    616 	return
    617 }
    618 
    619 // cgoIsGoPointer returns whether the pointer is a Go pointer--a
    620 // pointer to Go memory. We only care about Go memory that might
    621 // contain pointers.
    622 //go:nosplit
    623 //go:nowritebarrierrec
    624 func cgoIsGoPointer(p unsafe.Pointer) bool {
    625 	if p == nil {
    626 		return false
    627 	}
    628 
    629 	if inHeapOrStack(uintptr(p)) {
    630 		return true
    631 	}
    632 
    633 	for _, datap := range activeModules() {
    634 		if cgoInRange(p, datap.data, datap.edata) || cgoInRange(p, datap.bss, datap.ebss) {
    635 			return true
    636 		}
    637 	}
    638 
    639 	return false
    640 }
    641 
    642 // cgoInRange returns whether p is between start and end.
    643 //go:nosplit
    644 //go:nowritebarrierrec
    645 func cgoInRange(p unsafe.Pointer, start, end uintptr) bool {
    646 	return start <= uintptr(p) && uintptr(p) < end
    647 }
    648 
    649 // cgoCheckResult is called to check the result parameter of an
    650 // exported Go function. It panics if the result is or contains a Go
    651 // pointer.
    652 func cgoCheckResult(val interface{}) {
    653 	if debug.cgocheck == 0 {
    654 		return
    655 	}
    656 
    657 	ep := (*eface)(unsafe.Pointer(&val))
    658 	t := ep._type
    659 	cgoCheckArg(t, ep.data, t.kind&kindDirectIface == 0, false, cgoResultFail)
    660 }
    661