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