...

Source file src/runtime/cgocall.go

     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 != "illumos" && 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()
   129	
   130		mp.incgo = true
   131		errno := asmcgocall(fn, arg)
   132	
   133		// Update accounting before exitsyscall because exitsyscall may
   134		// reschedule us on to a different M.
   135		mp.incgo = false
   136		mp.ncgo--
   137	
   138		exitsyscall()
   139	
   140		// Note that raceacquire must be called only after exitsyscall has
   141		// wired this M to a P.
   142		if raceenabled {
   143			raceacquire(unsafe.Pointer(&racecgosync))
   144		}
   145	
   146		// From the garbage collector's perspective, time can move
   147		// backwards in the sequence above. If there's a callback into
   148		// Go code, GC will see this function at the call to
   149		// asmcgocall. When the Go call later returns to C, the
   150		// syscall PC/SP is rolled back and the GC sees this function
   151		// back at the call to entersyscall. Normally, fn and arg
   152		// would be live at entersyscall and dead at asmcgocall, so if
   153		// time moved backwards, GC would see these arguments as dead
   154		// and then live. Prevent these undead arguments from crashing
   155		// GC by forcing them to stay live across this time warp.
   156		KeepAlive(fn)
   157		KeepAlive(arg)
   158		KeepAlive(mp)
   159	
   160		return errno
   161	}
   162	
   163	// Call from C back to Go.
   164	//go:nosplit
   165	func cgocallbackg(ctxt uintptr) {
   166		gp := getg()
   167		if gp != gp.m.curg {
   168			println("runtime: bad g in cgocallback")
   169			exit(2)
   170		}
   171	
   172		// The call from C is on gp.m's g0 stack, so we must ensure
   173		// that we stay on that M. We have to do this before calling
   174		// exitsyscall, since it would otherwise be free to move us to
   175		// a different M. The call to unlockOSThread is in unwindm.
   176		lockOSThread()
   177	
   178		// Save current syscall parameters, so m.syscall can be
   179		// used again if callback decide to make syscall.
   180		syscall := gp.m.syscall
   181	
   182		// entersyscall saves the caller's SP to allow the GC to trace the Go
   183		// stack. However, since we're returning to an earlier stack frame and
   184		// need to pair with the entersyscall() call made by cgocall, we must
   185		// save syscall* and let reentersyscall restore them.
   186		savedsp := unsafe.Pointer(gp.syscallsp)
   187		savedpc := gp.syscallpc
   188		exitsyscall() // coming out of cgo call
   189		gp.m.incgo = false
   190	
   191		cgocallbackg1(ctxt)
   192	
   193		// At this point unlockOSThread has been called.
   194		// The following code must not change to a different m.
   195		// This is enforced by checking incgo in the schedule function.
   196	
   197		gp.m.incgo = true
   198		// going back to cgo call
   199		reentersyscall(savedpc, uintptr(savedsp))
   200	
   201		gp.m.syscall = syscall
   202	}
   203	
   204	func cgocallbackg1(ctxt uintptr) {
   205		gp := getg()
   206		if gp.m.needextram || atomic.Load(&extraMWaiters) > 0 {
   207			gp.m.needextram = false
   208			systemstack(newextram)
   209		}
   210	
   211		if ctxt != 0 {
   212			s := append(gp.cgoCtxt, ctxt)
   213	
   214			// Now we need to set gp.cgoCtxt = s, but we could get
   215			// a SIGPROF signal while manipulating the slice, and
   216			// the SIGPROF handler could pick up gp.cgoCtxt while
   217			// tracing up the stack.  We need to ensure that the
   218			// handler always sees a valid slice, so set the
   219			// values in an order such that it always does.
   220			p := (*slice)(unsafe.Pointer(&gp.cgoCtxt))
   221			atomicstorep(unsafe.Pointer(&p.array), unsafe.Pointer(&s[0]))
   222			p.cap = cap(s)
   223			p.len = len(s)
   224	
   225			defer func(gp *g) {
   226				// Decrease the length of the slice by one, safely.
   227				p := (*slice)(unsafe.Pointer(&gp.cgoCtxt))
   228				p.len--
   229			}(gp)
   230		}
   231	
   232		if gp.m.ncgo == 0 {
   233			// The C call to Go came from a thread not currently running
   234			// any Go. In the case of -buildmode=c-archive or c-shared,
   235			// this call may be coming in before package initialization
   236			// is complete. Wait until it is.
   237			<-main_init_done
   238		}
   239	
   240		// Add entry to defer stack in case of panic.
   241		restore := true
   242		defer unwindm(&restore)
   243	
   244		if raceenabled {
   245			raceacquire(unsafe.Pointer(&racecgosync))
   246		}
   247	
   248		type args struct {
   249			fn      *funcval
   250			arg     unsafe.Pointer
   251			argsize uintptr
   252		}
   253		var cb *args
   254	
   255		// Location of callback arguments depends on stack frame layout
   256		// and size of stack frame of cgocallback_gofunc.
   257		sp := gp.m.g0.sched.sp
   258		switch GOARCH {
   259		default:
   260			throw("cgocallbackg is unimplemented on arch")
   261		case "arm":
   262			// On arm, stack frame is two words and there's a saved LR between
   263			// SP and the stack frame and between the stack frame and the arguments.
   264			cb = (*args)(unsafe.Pointer(sp + 4*sys.PtrSize))
   265		case "arm64":
   266			// On arm64, stack frame is four words and there's a saved LR between
   267			// SP and the stack frame and between the stack frame and the arguments.
   268			// Additional two words (16-byte alignment) are for saving FP.
   269			cb = (*args)(unsafe.Pointer(sp + 7*sys.PtrSize))
   270		case "amd64":
   271			// On amd64, stack frame is two words, plus caller PC.
   272			if framepointer_enabled {
   273				// In this case, there's also saved BP.
   274				cb = (*args)(unsafe.Pointer(sp + 4*sys.PtrSize))
   275				break
   276			}
   277			cb = (*args)(unsafe.Pointer(sp + 3*sys.PtrSize))
   278		case "386":
   279			// On 386, stack frame is three words, plus caller PC.
   280			cb = (*args)(unsafe.Pointer(sp + 4*sys.PtrSize))
   281		case "ppc64", "ppc64le", "s390x":
   282			// On ppc64 and s390x, the callback arguments are in the arguments area of
   283			// cgocallback's stack frame. The stack looks like this:
   284			// +--------------------+------------------------------+
   285			// |                    | ...                          |
   286			// | cgoexp_$fn         +------------------------------+
   287			// |                    | fixed frame area             |
   288			// +--------------------+------------------------------+
   289			// |                    | arguments area               |
   290			// | cgocallback        +------------------------------+ <- sp + 2*minFrameSize + 2*ptrSize
   291			// |                    | fixed frame area             |
   292			// +--------------------+------------------------------+ <- sp + minFrameSize + 2*ptrSize
   293			// |                    | local variables (2 pointers) |
   294			// | cgocallback_gofunc +------------------------------+ <- sp + minFrameSize
   295			// |                    | fixed frame area             |
   296			// +--------------------+------------------------------+ <- sp
   297			cb = (*args)(unsafe.Pointer(sp + 2*sys.MinFrameSize + 2*sys.PtrSize))
   298		case "mips64", "mips64le":
   299			// On mips64x, stack frame is two words and there's a saved LR between
   300			// SP and the stack frame and between the stack frame and the arguments.
   301			cb = (*args)(unsafe.Pointer(sp + 4*sys.PtrSize))
   302		case "mips", "mipsle":
   303			// On mipsx, stack frame is two words and there's a saved LR between
   304			// SP and the stack frame and between the stack frame and the arguments.
   305			cb = (*args)(unsafe.Pointer(sp + 4*sys.PtrSize))
   306		}
   307	
   308		// Invoke callback.
   309		// NOTE(rsc): passing nil for argtype means that the copying of the
   310		// results back into cb.arg happens without any corresponding write barriers.
   311		// For cgo, cb.arg points into a C stack frame and therefore doesn't
   312		// hold any pointers that the GC can find anyway - the write barrier
   313		// would be a no-op.
   314		reflectcall(nil, unsafe.Pointer(cb.fn), cb.arg, uint32(cb.argsize), 0)
   315	
   316		if raceenabled {
   317			racereleasemerge(unsafe.Pointer(&racecgosync))
   318		}
   319		if msanenabled {
   320			// Tell msan that we wrote to the entire argument block.
   321			// This tells msan that we set the results.
   322			// Since we have already called the function it doesn't
   323			// matter that we are writing to the non-result parameters.
   324			msanwrite(cb.arg, cb.argsize)
   325		}
   326	
   327		// Do not unwind m->g0->sched.sp.
   328		// Our caller, cgocallback, will do that.
   329		restore = false
   330	}
   331	
   332	func unwindm(restore *bool) {
   333		if *restore {
   334			// Restore sp saved by cgocallback during
   335			// unwind of g's stack (see comment at top of file).
   336			mp := acquirem()
   337			sched := &mp.g0.sched
   338			switch GOARCH {
   339			default:
   340				throw("unwindm not implemented")
   341			case "386", "amd64", "arm", "ppc64", "ppc64le", "mips64", "mips64le", "s390x", "mips", "mipsle":
   342				sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + sys.MinFrameSize))
   343			case "arm64":
   344				sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + 16))
   345			}
   346	
   347			// Do the accounting that cgocall will not have a chance to do
   348			// during an unwind.
   349			//
   350			// In the case where a Go call originates from C, ncgo is 0
   351			// and there is no matching cgocall to end.
   352			if mp.ncgo > 0 {
   353				mp.incgo = false
   354				mp.ncgo--
   355			}
   356	
   357			releasem(mp)
   358		}
   359	
   360		// Undo the call to lockOSThread in cgocallbackg.
   361		// We must still stay on the same m.
   362		unlockOSThread()
   363	}
   364	
   365	// called from assembly
   366	func badcgocallback() {
   367		throw("misaligned stack in cgocallback")
   368	}
   369	
   370	// called from (incomplete) assembly
   371	func cgounimpl() {
   372		throw("cgo not implemented")
   373	}
   374	
   375	var racecgosync uint64 // represents possible synchronization in C code
   376	
   377	// Pointer checking for cgo code.
   378	
   379	// We want to detect all cases where a program that does not use
   380	// unsafe makes a cgo call passing a Go pointer to memory that
   381	// contains a Go pointer. Here a Go pointer is defined as a pointer
   382	// to memory allocated by the Go runtime. Programs that use unsafe
   383	// can evade this restriction easily, so we don't try to catch them.
   384	// The cgo program will rewrite all possibly bad pointer arguments to
   385	// call cgoCheckPointer, where we can catch cases of a Go pointer
   386	// pointing to a Go pointer.
   387	
   388	// Complicating matters, taking the address of a slice or array
   389	// element permits the C program to access all elements of the slice
   390	// or array. In that case we will see a pointer to a single element,
   391	// but we need to check the entire data structure.
   392	
   393	// The cgoCheckPointer call takes additional arguments indicating that
   394	// it was called on an address expression. An additional argument of
   395	// true means that it only needs to check a single element. An
   396	// additional argument of a slice or array means that it needs to
   397	// check the entire slice/array, but nothing else. Otherwise, the
   398	// pointer could be anything, and we check the entire heap object,
   399	// which is conservative but safe.
   400	
   401	// When and if we implement a moving garbage collector,
   402	// cgoCheckPointer will pin the pointer for the duration of the cgo
   403	// call.  (This is necessary but not sufficient; the cgo program will
   404	// also have to change to pin Go pointers that cannot point to Go
   405	// pointers.)
   406	
   407	// cgoCheckPointer checks if the argument contains a Go pointer that
   408	// points to a Go pointer, and panics if it does.
   409	func cgoCheckPointer(ptr interface{}, args ...interface{}) {
   410		if debug.cgocheck == 0 {
   411			return
   412		}
   413	
   414		ep := (*eface)(unsafe.Pointer(&ptr))
   415		t := ep._type
   416	
   417		top := true
   418		if len(args) > 0 && (t.kind&kindMask == kindPtr || t.kind&kindMask == kindUnsafePointer) {
   419			p := ep.data
   420			if t.kind&kindDirectIface == 0 {
   421				p = *(*unsafe.Pointer)(p)
   422			}
   423			if !cgoIsGoPointer(p) {
   424				return
   425			}
   426			aep := (*eface)(unsafe.Pointer(&args[0]))
   427			switch aep._type.kind & kindMask {
   428			case kindBool:
   429				if t.kind&kindMask == kindUnsafePointer {
   430					// We don't know the type of the element.
   431					break
   432				}
   433				pt := (*ptrtype)(unsafe.Pointer(t))
   434				cgoCheckArg(pt.elem, p, true, false, cgoCheckPointerFail)
   435				return
   436			case kindSlice:
   437				// Check the slice rather than the pointer.
   438				ep = aep
   439				t = ep._type
   440			case kindArray:
   441				// Check the array rather than the pointer.
   442				// Pass top as false since we have a pointer
   443				// to the array.
   444				ep = aep
   445				t = ep._type
   446				top = false
   447			default:
   448				throw("can't happen")
   449			}
   450		}
   451	
   452		cgoCheckArg(t, ep.data, t.kind&kindDirectIface == 0, top, cgoCheckPointerFail)
   453	}
   454	
   455	const cgoCheckPointerFail = "cgo argument has Go pointer to Go pointer"
   456	const cgoResultFail = "cgo result has Go pointer"
   457	
   458	// cgoCheckArg is the real work of cgoCheckPointer. The argument p
   459	// is either a pointer to the value (of type t), or the value itself,
   460	// depending on indir. The top parameter is whether we are at the top
   461	// level, where Go pointers are allowed.
   462	func cgoCheckArg(t *_type, p unsafe.Pointer, indir, top bool, msg string) {
   463		if t.ptrdata == 0 {
   464			// If the type has no pointers there is nothing to do.
   465			return
   466		}
   467	
   468		switch t.kind & kindMask {
   469		default:
   470			throw("can't happen")
   471		case kindArray:
   472			at := (*arraytype)(unsafe.Pointer(t))
   473			if !indir {
   474				if at.len != 1 {
   475					throw("can't happen")
   476				}
   477				cgoCheckArg(at.elem, p, at.elem.kind&kindDirectIface == 0, top, msg)
   478				return
   479			}
   480			for i := uintptr(0); i < at.len; i++ {
   481				cgoCheckArg(at.elem, p, true, top, msg)
   482				p = add(p, at.elem.size)
   483			}
   484		case kindChan, kindMap:
   485			// These types contain internal pointers that will
   486			// always be allocated in the Go heap. It's never OK
   487			// to pass them to C.
   488			panic(errorString(msg))
   489		case kindFunc:
   490			if indir {
   491				p = *(*unsafe.Pointer)(p)
   492			}
   493			if !cgoIsGoPointer(p) {
   494				return
   495			}
   496			panic(errorString(msg))
   497		case kindInterface:
   498			it := *(**_type)(p)
   499			if it == nil {
   500				return
   501			}
   502			// A type known at compile time is OK since it's
   503			// constant. A type not known at compile time will be
   504			// in the heap and will not be OK.
   505			if inheap(uintptr(unsafe.Pointer(it))) {
   506				panic(errorString(msg))
   507			}
   508			p = *(*unsafe.Pointer)(add(p, sys.PtrSize))
   509			if !cgoIsGoPointer(p) {
   510				return
   511			}
   512			if !top {
   513				panic(errorString(msg))
   514			}
   515			cgoCheckArg(it, p, it.kind&kindDirectIface == 0, false, msg)
   516		case kindSlice:
   517			st := (*slicetype)(unsafe.Pointer(t))
   518			s := (*slice)(p)
   519			p = s.array
   520			if !cgoIsGoPointer(p) {
   521				return
   522			}
   523			if !top {
   524				panic(errorString(msg))
   525			}
   526			if st.elem.ptrdata == 0 {
   527				return
   528			}
   529			for i := 0; i < s.cap; i++ {
   530				cgoCheckArg(st.elem, p, true, false, msg)
   531				p = add(p, st.elem.size)
   532			}
   533		case kindString:
   534			ss := (*stringStruct)(p)
   535			if !cgoIsGoPointer(ss.str) {
   536				return
   537			}
   538			if !top {
   539				panic(errorString(msg))
   540			}
   541		case kindStruct:
   542			st := (*structtype)(unsafe.Pointer(t))
   543			if !indir {
   544				if len(st.fields) != 1 {
   545					throw("can't happen")
   546				}
   547				cgoCheckArg(st.fields[0].typ, p, st.fields[0].typ.kind&kindDirectIface == 0, top, msg)
   548				return
   549			}
   550			for _, f := range st.fields {
   551				cgoCheckArg(f.typ, add(p, f.offset()), true, top, msg)
   552			}
   553		case kindPtr, kindUnsafePointer:
   554			if indir {
   555				p = *(*unsafe.Pointer)(p)
   556			}
   557	
   558			if !cgoIsGoPointer(p) {
   559				return
   560			}
   561			if !top {
   562				panic(errorString(msg))
   563			}
   564	
   565			cgoCheckUnknownPointer(p, msg)
   566		}
   567	}
   568	
   569	// cgoCheckUnknownPointer is called for an arbitrary pointer into Go
   570	// memory. It checks whether that Go memory contains any other
   571	// pointer into Go memory. If it does, we panic.
   572	// The return values are unused but useful to see in panic tracebacks.
   573	func cgoCheckUnknownPointer(p unsafe.Pointer, msg string) (base, i uintptr) {
   574		if inheap(uintptr(p)) {
   575			b, span, _ := findObject(uintptr(p), 0, 0)
   576			base = b
   577			if base == 0 {
   578				return
   579			}
   580			hbits := heapBitsForAddr(base)
   581			n := span.elemsize
   582			for i = uintptr(0); i < n; i += sys.PtrSize {
   583				if i != 1*sys.PtrSize && !hbits.morePointers() {
   584					// No more possible pointers.
   585					break
   586				}
   587				if hbits.isPointer() && cgoIsGoPointer(*(*unsafe.Pointer)(unsafe.Pointer(base + i))) {
   588					panic(errorString(msg))
   589				}
   590				hbits = hbits.next()
   591			}
   592	
   593			return
   594		}
   595	
   596		for _, datap := range activeModules() {
   597			if cgoInRange(p, datap.data, datap.edata) || cgoInRange(p, datap.bss, datap.ebss) {
   598				// We have no way to know the size of the object.
   599				// We have to assume that it might contain a pointer.
   600				panic(errorString(msg))
   601			}
   602			// In the text or noptr sections, we know that the
   603			// pointer does not point to a Go pointer.
   604		}
   605	
   606		return
   607	}
   608	
   609	// cgoIsGoPointer reports whether the pointer is a Go pointer--a
   610	// pointer to Go memory. We only care about Go memory that might
   611	// contain pointers.
   612	//go:nosplit
   613	//go:nowritebarrierrec
   614	func cgoIsGoPointer(p unsafe.Pointer) bool {
   615		if p == nil {
   616			return false
   617		}
   618	
   619		if inHeapOrStack(uintptr(p)) {
   620			return true
   621		}
   622	
   623		for _, datap := range activeModules() {
   624			if cgoInRange(p, datap.data, datap.edata) || cgoInRange(p, datap.bss, datap.ebss) {
   625				return true
   626			}
   627		}
   628	
   629		return false
   630	}
   631	
   632	// cgoInRange reports whether p is between start and end.
   633	//go:nosplit
   634	//go:nowritebarrierrec
   635	func cgoInRange(p unsafe.Pointer, start, end uintptr) bool {
   636		return start <= uintptr(p) && uintptr(p) < end
   637	}
   638	
   639	// cgoCheckResult is called to check the result parameter of an
   640	// exported Go function. It panics if the result is or contains a Go
   641	// pointer.
   642	func cgoCheckResult(val interface{}) {
   643		if debug.cgocheck == 0 {
   644			return
   645		}
   646	
   647		ep := (*eface)(unsafe.Pointer(&val))
   648		t := ep._type
   649		cgoCheckArg(t, ep.data, t.kind&kindDirectIface == 0, false, cgoResultFail)
   650	}
   651	

View as plain text