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 initializes "frame", a structure containing all of its 39 // arguments and slots for p.GoF's results. It calls 40 // crosscall2(_cgoexp_GoF, frame, framesize, ctxt) using the gcc ABI. 41 // 42 // crosscall2 (in cgo/asm_$GOARCH.s) is a four-argument adapter from 43 // the gcc function call ABI to the gc function call ABI. At this 44 // point we're in the Go runtime, but we're still running on m.g0's 45 // stack and outside the $GOMAXPROCS limit. crosscall2 calls 46 // runtime.cgocallback(_cgoexp_GoF, frame, ctxt) using the gc ABI. 47 // (crosscall2's framesize argument is no longer used, but there's one 48 // case where SWIG calls crosscall2 directly and expects to pass this 49 // argument. See _cgo_panic.) 50 // 51 // runtime.cgocallback (in asm_$GOARCH.s) switches from m.g0's stack 52 // to the original g (m.curg)'s stack, on which it calls 53 // runtime.cgocallbackg(_cgoexp_GoF, frame, ctxt). As part of the 54 // stack switch, runtime.cgocallback saves the current SP as 55 // m.g0.sched.sp, so that any use of m.g0's stack during the execution 56 // of the callback will be done below the existing stack frames. 57 // Before overwriting m.g0.sched.sp, it pushes the old value on the 58 // m.g0 stack, so that it can be restored later. 59 // 60 // runtime.cgocallbackg (below) is now running on a real goroutine 61 // stack (not an m.g0 stack). First it calls runtime.exitsyscall, which will 62 // block until the $GOMAXPROCS limit allows running this goroutine. 63 // Once exitsyscall has returned, it is safe to do things like call the memory 64 // allocator or invoke the Go callback function. runtime.cgocallbackg 65 // first defers a function to unwind m.g0.sched.sp, so that if p.GoF 66 // panics, m.g0.sched.sp will be restored to its old value: the m.g0 stack 67 // and the m.curg stack will be unwound in lock step. 68 // Then it calls _cgoexp_GoF(frame). 69 // 70 // _cgoexp_GoF, which was generated by cmd/cgo, unpacks the arguments 71 // from frame, calls p.GoF, writes the results back to frame, and 72 // returns. Now we start unwinding this whole process. 73 // 74 // runtime.cgocallbackg pops but does not execute the deferred 75 // function to unwind m.g0.sched.sp, calls runtime.entersyscall, and 76 // returns to runtime.cgocallback. 77 // 78 // After it regains control, runtime.cgocallback switches back to 79 // m.g0's stack (the pointer is still in m.g0.sched.sp), restores the old 80 // m.g0.sched.sp value from the stack, and returns to crosscall2. 81 // 82 // crosscall2 restores the callee-save registers for gcc and returns 83 // to GoF, which unpacks any result values and returns to f. 84 85 package runtime 86 87 import ( 88 "internal/abi" 89 "internal/goarch" 90 "internal/goexperiment" 91 "runtime/internal/sys" 92 "unsafe" 93 ) 94 95 // Addresses collected in a cgo backtrace when crashing. 96 // Length must match arg.Max in x_cgo_callers in runtime/cgo/gcc_traceback.c. 97 type cgoCallers [32]uintptr 98 99 // argset matches runtime/cgo/linux_syscall.c:argset_t 100 type argset struct { 101 args unsafe.Pointer 102 retval uintptr 103 } 104 105 // wrapper for syscall package to call cgocall for libc (cgo) calls. 106 // 107 //go:linkname syscall_cgocaller syscall.cgocaller 108 //go:nosplit 109 //go:uintptrescapes 110 func syscall_cgocaller(fn unsafe.Pointer, args ...uintptr) uintptr { 111 as := argset{args: unsafe.Pointer(&args[0])} 112 cgocall(fn, unsafe.Pointer(&as)) 113 return as.retval 114 } 115 116 var ncgocall uint64 // number of cgo calls in total for dead m 117 118 // Call from Go to C. 119 // 120 // This must be nosplit because it's used for syscalls on some 121 // platforms. Syscalls may have untyped arguments on the stack, so 122 // it's not safe to grow or scan the stack. 123 // 124 //go:nosplit 125 func cgocall(fn, arg unsafe.Pointer) int32 { 126 if !iscgo && GOOS != "solaris" && GOOS != "illumos" && GOOS != "windows" { 127 throw("cgocall unavailable") 128 } 129 130 if fn == nil { 131 throw("cgocall nil") 132 } 133 134 if raceenabled { 135 racereleasemerge(unsafe.Pointer(&racecgosync)) 136 } 137 138 mp := getg().m 139 mp.ncgocall++ 140 141 // Reset traceback. 142 mp.cgoCallers[0] = 0 143 144 // Announce we are entering a system call 145 // so that the scheduler knows to create another 146 // M to run goroutines while we are in the 147 // foreign code. 148 // 149 // The call to asmcgocall is guaranteed not to 150 // grow the stack and does not allocate memory, 151 // so it is safe to call while "in a system call", outside 152 // the $GOMAXPROCS accounting. 153 // 154 // fn may call back into Go code, in which case we'll exit the 155 // "system call", run the Go code (which may grow the stack), 156 // and then re-enter the "system call" reusing the PC and SP 157 // saved by entersyscall here. 158 entersyscall() 159 160 // Tell asynchronous preemption that we're entering external 161 // code. We do this after entersyscall because this may block 162 // and cause an async preemption to fail, but at this point a 163 // sync preemption will succeed (though this is not a matter 164 // of correctness). 165 osPreemptExtEnter(mp) 166 167 mp.incgo = true 168 // We use ncgo as a check during execution tracing for whether there is 169 // any C on the call stack, which there will be after this point. If 170 // there isn't, we can use frame pointer unwinding to collect call 171 // stacks efficiently. This will be the case for the first Go-to-C call 172 // on a stack, so it's preferable to update it here, after we emit a 173 // trace event in entersyscall above. 174 mp.ncgo++ 175 176 errno := asmcgocall(fn, arg) 177 178 // Update accounting before exitsyscall because exitsyscall may 179 // reschedule us on to a different M. 180 mp.incgo = false 181 mp.ncgo-- 182 183 osPreemptExtExit(mp) 184 185 // Save current syscall parameters, so m.winsyscall can be 186 // used again if callback decide to make syscall. 187 winsyscall := mp.winsyscall 188 189 exitsyscall() 190 191 getg().m.winsyscall = winsyscall 192 193 // Note that raceacquire must be called only after exitsyscall has 194 // wired this M to a P. 195 if raceenabled { 196 raceacquire(unsafe.Pointer(&racecgosync)) 197 } 198 199 // From the garbage collector's perspective, time can move 200 // backwards in the sequence above. If there's a callback into 201 // Go code, GC will see this function at the call to 202 // asmcgocall. When the Go call later returns to C, the 203 // syscall PC/SP is rolled back and the GC sees this function 204 // back at the call to entersyscall. Normally, fn and arg 205 // would be live at entersyscall and dead at asmcgocall, so if 206 // time moved backwards, GC would see these arguments as dead 207 // and then live. Prevent these undead arguments from crashing 208 // GC by forcing them to stay live across this time warp. 209 KeepAlive(fn) 210 KeepAlive(arg) 211 KeepAlive(mp) 212 213 return errno 214 } 215 216 // Set or reset the system stack bounds for a callback on sp. 217 // 218 // Must be nosplit because it is called by needm prior to fully initializing 219 // the M. 220 // 221 //go:nosplit 222 func callbackUpdateSystemStack(mp *m, sp uintptr, signal bool) { 223 g0 := mp.g0 224 if sp > g0.stack.lo && sp <= g0.stack.hi { 225 // Stack already in bounds, nothing to do. 226 return 227 } 228 229 if mp.ncgo > 0 { 230 // ncgo > 0 indicates that this M was in Go further up the stack 231 // (it called C and is now receiving a callback). It is not 232 // safe for the C call to change the stack out from under us. 233 234 // Note that this case isn't possible for signal == true, as 235 // that is always passing a new M from needm. 236 237 // Stack is bogus, but reset the bounds anyway so we can print. 238 hi := g0.stack.hi 239 lo := g0.stack.lo 240 g0.stack.hi = sp + 1024 241 g0.stack.lo = sp - 32*1024 242 g0.stackguard0 = g0.stack.lo + stackGuard 243 g0.stackguard1 = g0.stackguard0 244 245 print("M ", mp.id, " procid ", mp.procid, " runtime: cgocallback with sp=", hex(sp), " out of bounds [", hex(lo), ", ", hex(hi), "]") 246 print("\n") 247 exit(2) 248 } 249 250 // This M does not have Go further up the stack. However, it may have 251 // previously called into Go, initializing the stack bounds. Between 252 // that call returning and now the stack may have changed (perhaps the 253 // C thread is running a coroutine library). We need to update the 254 // stack bounds for this case. 255 // 256 // Set the stack bounds to match the current stack. If we don't 257 // actually know how big the stack is, like we don't know how big any 258 // scheduling stack is, but we assume there's at least 32 kB. If we 259 // can get a more accurate stack bound from pthread, use that, provided 260 // it actually contains SP.. 261 g0.stack.hi = sp + 1024 262 g0.stack.lo = sp - 32*1024 263 if !signal && _cgo_getstackbound != nil { 264 // Don't adjust if called from the signal handler. 265 // We are on the signal stack, not the pthread stack. 266 // (We could get the stack bounds from sigaltstack, but 267 // we're getting out of the signal handler very soon 268 // anyway. Not worth it.) 269 var bounds [2]uintptr 270 asmcgocall(_cgo_getstackbound, unsafe.Pointer(&bounds)) 271 // getstackbound is an unsupported no-op on Windows. 272 // 273 // Don't use these bounds if they don't contain SP. Perhaps we 274 // were called by something not using the standard thread 275 // stack. 276 if bounds[0] != 0 && sp > bounds[0] && sp <= bounds[1] { 277 g0.stack.lo = bounds[0] 278 g0.stack.hi = bounds[1] 279 } 280 } 281 g0.stackguard0 = g0.stack.lo + stackGuard 282 g0.stackguard1 = g0.stackguard0 283 } 284 285 // Call from C back to Go. fn must point to an ABIInternal Go entry-point. 286 // 287 //go:nosplit 288 func cgocallbackg(fn, frame unsafe.Pointer, ctxt uintptr) { 289 gp := getg() 290 if gp != gp.m.curg { 291 println("runtime: bad g in cgocallback") 292 exit(2) 293 } 294 295 sp := gp.m.g0.sched.sp // system sp saved by cgocallback. 296 callbackUpdateSystemStack(gp.m, sp, false) 297 298 // The call from C is on gp.m's g0 stack, so we must ensure 299 // that we stay on that M. We have to do this before calling 300 // exitsyscall, since it would otherwise be free to move us to 301 // a different M. The call to unlockOSThread is in this function 302 // after cgocallbackg1, or in the case of panicking, in unwindm. 303 lockOSThread() 304 305 checkm := gp.m 306 307 // Save current syscall parameters, so m.winsyscall can be 308 // used again if callback decide to make syscall. 309 winsyscall := gp.m.winsyscall 310 311 // entersyscall saves the caller's SP to allow the GC to trace the Go 312 // stack. However, since we're returning to an earlier stack frame and 313 // need to pair with the entersyscall() call made by cgocall, we must 314 // save syscall* and let reentersyscall restore them. 315 savedsp := unsafe.Pointer(gp.syscallsp) 316 savedpc := gp.syscallpc 317 savedbp := gp.syscallbp 318 exitsyscall() // coming out of cgo call 319 gp.m.incgo = false 320 if gp.m.isextra { 321 gp.m.isExtraInC = false 322 } 323 324 osPreemptExtExit(gp.m) 325 326 if gp.nocgocallback { 327 panic("runtime: function marked with #cgo nocallback called back into Go") 328 } 329 330 cgocallbackg1(fn, frame, ctxt) 331 332 // At this point we're about to call unlockOSThread. 333 // The following code must not change to a different m. 334 // This is enforced by checking incgo in the schedule function. 335 gp.m.incgo = true 336 unlockOSThread() 337 338 if gp.m.isextra { 339 gp.m.isExtraInC = true 340 } 341 342 if gp.m != checkm { 343 throw("m changed unexpectedly in cgocallbackg") 344 } 345 346 osPreemptExtEnter(gp.m) 347 348 // going back to cgo call 349 reentersyscall(savedpc, uintptr(savedsp), savedbp) 350 351 gp.m.winsyscall = winsyscall 352 } 353 354 func cgocallbackg1(fn, frame unsafe.Pointer, ctxt uintptr) { 355 gp := getg() 356 357 if gp.m.needextram || extraMWaiters.Load() > 0 { 358 gp.m.needextram = false 359 systemstack(newextram) 360 } 361 362 if ctxt != 0 { 363 s := append(gp.cgoCtxt, ctxt) 364 365 // Now we need to set gp.cgoCtxt = s, but we could get 366 // a SIGPROF signal while manipulating the slice, and 367 // the SIGPROF handler could pick up gp.cgoCtxt while 368 // tracing up the stack. We need to ensure that the 369 // handler always sees a valid slice, so set the 370 // values in an order such that it always does. 371 p := (*slice)(unsafe.Pointer(&gp.cgoCtxt)) 372 atomicstorep(unsafe.Pointer(&p.array), unsafe.Pointer(&s[0])) 373 p.cap = cap(s) 374 p.len = len(s) 375 376 defer func(gp *g) { 377 // Decrease the length of the slice by one, safely. 378 p := (*slice)(unsafe.Pointer(&gp.cgoCtxt)) 379 p.len-- 380 }(gp) 381 } 382 383 if gp.m.ncgo == 0 { 384 // The C call to Go came from a thread not currently running 385 // any Go. In the case of -buildmode=c-archive or c-shared, 386 // this call may be coming in before package initialization 387 // is complete. Wait until it is. 388 <-main_init_done 389 } 390 391 // Check whether the profiler needs to be turned on or off; this route to 392 // run Go code does not use runtime.execute, so bypasses the check there. 393 hz := sched.profilehz 394 if gp.m.profilehz != hz { 395 setThreadCPUProfiler(hz) 396 } 397 398 // Add entry to defer stack in case of panic. 399 restore := true 400 defer unwindm(&restore) 401 402 if raceenabled { 403 raceacquire(unsafe.Pointer(&racecgosync)) 404 } 405 406 // Invoke callback. This function is generated by cmd/cgo and 407 // will unpack the argument frame and call the Go function. 408 var cb func(frame unsafe.Pointer) 409 cbFV := funcval{uintptr(fn)} 410 *(*unsafe.Pointer)(unsafe.Pointer(&cb)) = noescape(unsafe.Pointer(&cbFV)) 411 cb(frame) 412 413 if raceenabled { 414 racereleasemerge(unsafe.Pointer(&racecgosync)) 415 } 416 417 // Do not unwind m->g0->sched.sp. 418 // Our caller, cgocallback, will do that. 419 restore = false 420 } 421 422 func unwindm(restore *bool) { 423 if *restore { 424 // Restore sp saved by cgocallback during 425 // unwind of g's stack (see comment at top of file). 426 mp := acquirem() 427 sched := &mp.g0.sched 428 sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + alignUp(sys.MinFrameSize, sys.StackAlign))) 429 430 // Do the accounting that cgocall will not have a chance to do 431 // during an unwind. 432 // 433 // In the case where a Go call originates from C, ncgo is 0 434 // and there is no matching cgocall to end. 435 if mp.ncgo > 0 { 436 mp.incgo = false 437 mp.ncgo-- 438 osPreemptExtExit(mp) 439 } 440 441 // Undo the call to lockOSThread in cgocallbackg, only on the 442 // panicking path. In normal return case cgocallbackg will call 443 // unlockOSThread, ensuring no preemption point after the unlock. 444 // Here we don't need to worry about preemption, because we're 445 // panicking out of the callback and unwinding the g0 stack, 446 // instead of reentering cgo (which requires the same thread). 447 unlockOSThread() 448 449 releasem(mp) 450 } 451 } 452 453 // called from assembly. 454 func badcgocallback() { 455 throw("misaligned stack in cgocallback") 456 } 457 458 // called from (incomplete) assembly. 459 func cgounimpl() { 460 throw("cgo not implemented") 461 } 462 463 var racecgosync uint64 // represents possible synchronization in C code 464 465 // Pointer checking for cgo code. 466 467 // We want to detect all cases where a program that does not use 468 // unsafe makes a cgo call passing a Go pointer to memory that 469 // contains an unpinned Go pointer. Here a Go pointer is defined as a 470 // pointer to memory allocated by the Go runtime. Programs that use 471 // unsafe can evade this restriction easily, so we don't try to catch 472 // them. The cgo program will rewrite all possibly bad pointer 473 // arguments to call cgoCheckPointer, where we can catch cases of a Go 474 // pointer pointing to an unpinned Go pointer. 475 476 // Complicating matters, taking the address of a slice or array 477 // element permits the C program to access all elements of the slice 478 // or array. In that case we will see a pointer to a single element, 479 // but we need to check the entire data structure. 480 481 // The cgoCheckPointer call takes additional arguments indicating that 482 // it was called on an address expression. An additional argument of 483 // true means that it only needs to check a single element. An 484 // additional argument of a slice or array means that it needs to 485 // check the entire slice/array, but nothing else. Otherwise, the 486 // pointer could be anything, and we check the entire heap object, 487 // which is conservative but safe. 488 489 // When and if we implement a moving garbage collector, 490 // cgoCheckPointer will pin the pointer for the duration of the cgo 491 // call. (This is necessary but not sufficient; the cgo program will 492 // also have to change to pin Go pointers that cannot point to Go 493 // pointers.) 494 495 // cgoCheckPointer checks if the argument contains a Go pointer that 496 // points to an unpinned Go pointer, and panics if it does. 497 func cgoCheckPointer(ptr any, arg any) { 498 if !goexperiment.CgoCheck2 && debug.cgocheck == 0 { 499 return 500 } 501 502 ep := efaceOf(&ptr) 503 t := ep._type 504 505 top := true 506 if arg != nil && (t.Kind_&abi.KindMask == abi.Pointer || t.Kind_&abi.KindMask == abi.UnsafePointer) { 507 p := ep.data 508 if t.Kind_&abi.KindDirectIface == 0 { 509 p = *(*unsafe.Pointer)(p) 510 } 511 if p == nil || !cgoIsGoPointer(p) { 512 return 513 } 514 aep := efaceOf(&arg) 515 switch aep._type.Kind_ & abi.KindMask { 516 case abi.Bool: 517 if t.Kind_&abi.KindMask == abi.UnsafePointer { 518 // We don't know the type of the element. 519 break 520 } 521 pt := (*ptrtype)(unsafe.Pointer(t)) 522 cgoCheckArg(pt.Elem, p, true, false, cgoCheckPointerFail) 523 return 524 case abi.Slice: 525 // Check the slice rather than the pointer. 526 ep = aep 527 t = ep._type 528 case abi.Array: 529 // Check the array rather than the pointer. 530 // Pass top as false since we have a pointer 531 // to the array. 532 ep = aep 533 t = ep._type 534 top = false 535 default: 536 throw("can't happen") 537 } 538 } 539 540 cgoCheckArg(t, ep.data, t.Kind_&abi.KindDirectIface == 0, top, cgoCheckPointerFail) 541 } 542 543 const cgoCheckPointerFail = "cgo argument has Go pointer to unpinned Go pointer" 544 const cgoResultFail = "cgo result is unpinned Go pointer or points to unpinned Go pointer" 545 546 // cgoCheckArg is the real work of cgoCheckPointer. The argument p 547 // is either a pointer to the value (of type t), or the value itself, 548 // depending on indir. The top parameter is whether we are at the top 549 // level, where Go pointers are allowed. Go pointers to pinned objects are 550 // allowed as long as they don't reference other unpinned pointers. 551 func cgoCheckArg(t *_type, p unsafe.Pointer, indir, top bool, msg string) { 552 if !t.Pointers() || p == nil { 553 // If the type has no pointers there is nothing to do. 554 return 555 } 556 557 switch t.Kind_ & abi.KindMask { 558 default: 559 throw("can't happen") 560 case abi.Array: 561 at := (*arraytype)(unsafe.Pointer(t)) 562 if !indir { 563 if at.Len != 1 { 564 throw("can't happen") 565 } 566 cgoCheckArg(at.Elem, p, at.Elem.Kind_&abi.KindDirectIface == 0, top, msg) 567 return 568 } 569 for i := uintptr(0); i < at.Len; i++ { 570 cgoCheckArg(at.Elem, p, true, top, msg) 571 p = add(p, at.Elem.Size_) 572 } 573 case abi.Chan, abi.Map: 574 // These types contain internal pointers that will 575 // always be allocated in the Go heap. It's never OK 576 // to pass them to C. 577 panic(errorString(msg)) 578 case abi.Func: 579 if indir { 580 p = *(*unsafe.Pointer)(p) 581 } 582 if !cgoIsGoPointer(p) { 583 return 584 } 585 panic(errorString(msg)) 586 case abi.Interface: 587 it := *(**_type)(p) 588 if it == nil { 589 return 590 } 591 // A type known at compile time is OK since it's 592 // constant. A type not known at compile time will be 593 // in the heap and will not be OK. 594 if inheap(uintptr(unsafe.Pointer(it))) { 595 panic(errorString(msg)) 596 } 597 p = *(*unsafe.Pointer)(add(p, goarch.PtrSize)) 598 if !cgoIsGoPointer(p) { 599 return 600 } 601 if !top && !isPinned(p) { 602 panic(errorString(msg)) 603 } 604 cgoCheckArg(it, p, it.Kind_&abi.KindDirectIface == 0, false, msg) 605 case abi.Slice: 606 st := (*slicetype)(unsafe.Pointer(t)) 607 s := (*slice)(p) 608 p = s.array 609 if p == nil || !cgoIsGoPointer(p) { 610 return 611 } 612 if !top && !isPinned(p) { 613 panic(errorString(msg)) 614 } 615 if !st.Elem.Pointers() { 616 return 617 } 618 for i := 0; i < s.cap; i++ { 619 cgoCheckArg(st.Elem, p, true, false, msg) 620 p = add(p, st.Elem.Size_) 621 } 622 case abi.String: 623 ss := (*stringStruct)(p) 624 if !cgoIsGoPointer(ss.str) { 625 return 626 } 627 if !top && !isPinned(ss.str) { 628 panic(errorString(msg)) 629 } 630 case abi.Struct: 631 st := (*structtype)(unsafe.Pointer(t)) 632 if !indir { 633 if len(st.Fields) != 1 { 634 throw("can't happen") 635 } 636 cgoCheckArg(st.Fields[0].Typ, p, st.Fields[0].Typ.Kind_&abi.KindDirectIface == 0, top, msg) 637 return 638 } 639 for _, f := range st.Fields { 640 if !f.Typ.Pointers() { 641 continue 642 } 643 cgoCheckArg(f.Typ, add(p, f.Offset), true, top, msg) 644 } 645 case abi.Pointer, abi.UnsafePointer: 646 if indir { 647 p = *(*unsafe.Pointer)(p) 648 if p == nil { 649 return 650 } 651 } 652 653 if !cgoIsGoPointer(p) { 654 return 655 } 656 if !top && !isPinned(p) { 657 panic(errorString(msg)) 658 } 659 660 cgoCheckUnknownPointer(p, msg) 661 } 662 } 663 664 // cgoCheckUnknownPointer is called for an arbitrary pointer into Go 665 // memory. It checks whether that Go memory contains any other 666 // pointer into unpinned Go memory. If it does, we panic. 667 // The return values are unused but useful to see in panic tracebacks. 668 func cgoCheckUnknownPointer(p unsafe.Pointer, msg string) (base, i uintptr) { 669 if inheap(uintptr(p)) { 670 b, span, _ := findObject(uintptr(p), 0, 0) 671 base = b 672 if base == 0 { 673 return 674 } 675 tp := span.typePointersOfUnchecked(base) 676 for { 677 var addr uintptr 678 if tp, addr = tp.next(base + span.elemsize); addr == 0 { 679 break 680 } 681 pp := *(*unsafe.Pointer)(unsafe.Pointer(addr)) 682 if cgoIsGoPointer(pp) && !isPinned(pp) { 683 panic(errorString(msg)) 684 } 685 } 686 return 687 } 688 689 for _, datap := range activeModules() { 690 if cgoInRange(p, datap.data, datap.edata) || cgoInRange(p, datap.bss, datap.ebss) { 691 // We have no way to know the size of the object. 692 // We have to assume that it might contain a pointer. 693 panic(errorString(msg)) 694 } 695 // In the text or noptr sections, we know that the 696 // pointer does not point to a Go pointer. 697 } 698 699 return 700 } 701 702 // cgoIsGoPointer reports whether the pointer is a Go pointer--a 703 // pointer to Go memory. We only care about Go memory that might 704 // contain pointers. 705 // 706 //go:nosplit 707 //go:nowritebarrierrec 708 func cgoIsGoPointer(p unsafe.Pointer) bool { 709 if p == nil { 710 return false 711 } 712 713 if inHeapOrStack(uintptr(p)) { 714 return true 715 } 716 717 for _, datap := range activeModules() { 718 if cgoInRange(p, datap.data, datap.edata) || cgoInRange(p, datap.bss, datap.ebss) { 719 return true 720 } 721 } 722 723 return false 724 } 725 726 // cgoInRange reports whether p is between start and end. 727 // 728 //go:nosplit 729 //go:nowritebarrierrec 730 func cgoInRange(p unsafe.Pointer, start, end uintptr) bool { 731 return start <= uintptr(p) && uintptr(p) < end 732 } 733 734 // cgoCheckResult is called to check the result parameter of an 735 // exported Go function. It panics if the result is or contains any 736 // other pointer into unpinned Go memory. 737 func cgoCheckResult(val any) { 738 if !goexperiment.CgoCheck2 && debug.cgocheck == 0 { 739 return 740 } 741 742 ep := efaceOf(&val) 743 t := ep._type 744 cgoCheckArg(t, ep.data, t.Kind_&abi.KindDirectIface == 0, false, cgoResultFail) 745 } 746