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 225 inBound := sp > g0.stack.lo && sp <= g0.stack.hi 226 if mp.ncgo > 0 && !inBound { 227 // ncgo > 0 indicates that this M was in Go further up the stack 228 // (it called C and is now receiving a callback). 229 // 230 // !inBound indicates that we were called with SP outside the 231 // expected system stack bounds (C changed the stack out from 232 // under us between the cgocall and cgocallback?). 233 // 234 // It is not safe for the C call to change the stack out from 235 // under us, so throw. 236 237 // Note that this case isn't possible for signal == true, as 238 // that is always passing a new M from needm. 239 240 // Stack is bogus, but reset the bounds anyway so we can print. 241 hi := g0.stack.hi 242 lo := g0.stack.lo 243 g0.stack.hi = sp + 1024 244 g0.stack.lo = sp - 32*1024 245 g0.stackguard0 = g0.stack.lo + stackGuard 246 g0.stackguard1 = g0.stackguard0 247 248 print("M ", mp.id, " procid ", mp.procid, " runtime: cgocallback with sp=", hex(sp), " out of bounds [", hex(lo), ", ", hex(hi), "]") 249 print("\n") 250 exit(2) 251 } 252 253 if !mp.isextra { 254 // We allocated the stack for standard Ms. Don't replace the 255 // stack bounds with estimated ones when we already initialized 256 // with the exact ones. 257 return 258 } 259 260 // This M does not have Go further up the stack. However, it may have 261 // previously called into Go, initializing the stack bounds. Between 262 // that call returning and now the stack may have changed (perhaps the 263 // C thread is running a coroutine library). We need to update the 264 // stack bounds for this case. 265 // 266 // N.B. we need to update the stack bounds even if SP appears to 267 // already be in bounds. Our "bounds" may actually be estimated dummy 268 // bounds (below). The actual stack bounds could have shifted but still 269 // have partial overlap with our dummy bounds. If we failed to update 270 // in that case, we could find ourselves seemingly called near the 271 // bottom of the stack bounds, where we quickly run out of space. 272 273 // Set the stack bounds to match the current stack. If we don't 274 // actually know how big the stack is, like we don't know how big any 275 // scheduling stack is, but we assume there's at least 32 kB. If we 276 // can get a more accurate stack bound from pthread, use that, provided 277 // it actually contains SP.. 278 g0.stack.hi = sp + 1024 279 g0.stack.lo = sp - 32*1024 280 if !signal && _cgo_getstackbound != nil { 281 // Don't adjust if called from the signal handler. 282 // We are on the signal stack, not the pthread stack. 283 // (We could get the stack bounds from sigaltstack, but 284 // we're getting out of the signal handler very soon 285 // anyway. Not worth it.) 286 var bounds [2]uintptr 287 asmcgocall(_cgo_getstackbound, unsafe.Pointer(&bounds)) 288 // getstackbound is an unsupported no-op on Windows. 289 // 290 // Don't use these bounds if they don't contain SP. Perhaps we 291 // were called by something not using the standard thread 292 // stack. 293 if bounds[0] != 0 && sp > bounds[0] && sp <= bounds[1] { 294 g0.stack.lo = bounds[0] 295 g0.stack.hi = bounds[1] 296 } 297 } 298 g0.stackguard0 = g0.stack.lo + stackGuard 299 g0.stackguard1 = g0.stackguard0 300 } 301 302 // Call from C back to Go. fn must point to an ABIInternal Go entry-point. 303 // 304 //go:nosplit 305 func cgocallbackg(fn, frame unsafe.Pointer, ctxt uintptr) { 306 gp := getg() 307 if gp != gp.m.curg { 308 println("runtime: bad g in cgocallback") 309 exit(2) 310 } 311 312 sp := gp.m.g0.sched.sp // system sp saved by cgocallback. 313 callbackUpdateSystemStack(gp.m, sp, false) 314 315 // The call from C is on gp.m's g0 stack, so we must ensure 316 // that we stay on that M. We have to do this before calling 317 // exitsyscall, since it would otherwise be free to move us to 318 // a different M. The call to unlockOSThread is in this function 319 // after cgocallbackg1, or in the case of panicking, in unwindm. 320 lockOSThread() 321 322 checkm := gp.m 323 324 // Save current syscall parameters, so m.winsyscall can be 325 // used again if callback decide to make syscall. 326 winsyscall := gp.m.winsyscall 327 328 // entersyscall saves the caller's SP to allow the GC to trace the Go 329 // stack. However, since we're returning to an earlier stack frame and 330 // need to pair with the entersyscall() call made by cgocall, we must 331 // save syscall* and let reentersyscall restore them. 332 savedsp := unsafe.Pointer(gp.syscallsp) 333 savedpc := gp.syscallpc 334 savedbp := gp.syscallbp 335 exitsyscall() // coming out of cgo call 336 gp.m.incgo = false 337 if gp.m.isextra { 338 gp.m.isExtraInC = false 339 } 340 341 osPreemptExtExit(gp.m) 342 343 if gp.nocgocallback { 344 panic("runtime: function marked with #cgo nocallback called back into Go") 345 } 346 347 cgocallbackg1(fn, frame, ctxt) 348 349 // At this point we're about to call unlockOSThread. 350 // The following code must not change to a different m. 351 // This is enforced by checking incgo in the schedule function. 352 gp.m.incgo = true 353 unlockOSThread() 354 355 if gp.m.isextra { 356 gp.m.isExtraInC = true 357 } 358 359 if gp.m != checkm { 360 throw("m changed unexpectedly in cgocallbackg") 361 } 362 363 osPreemptExtEnter(gp.m) 364 365 // going back to cgo call 366 reentersyscall(savedpc, uintptr(savedsp), savedbp) 367 368 gp.m.winsyscall = winsyscall 369 } 370 371 func cgocallbackg1(fn, frame unsafe.Pointer, ctxt uintptr) { 372 gp := getg() 373 374 if gp.m.needextram || extraMWaiters.Load() > 0 { 375 gp.m.needextram = false 376 systemstack(newextram) 377 } 378 379 if ctxt != 0 { 380 s := append(gp.cgoCtxt, ctxt) 381 382 // Now we need to set gp.cgoCtxt = s, but we could get 383 // a SIGPROF signal while manipulating the slice, and 384 // the SIGPROF handler could pick up gp.cgoCtxt while 385 // tracing up the stack. We need to ensure that the 386 // handler always sees a valid slice, so set the 387 // values in an order such that it always does. 388 p := (*slice)(unsafe.Pointer(&gp.cgoCtxt)) 389 atomicstorep(unsafe.Pointer(&p.array), unsafe.Pointer(&s[0])) 390 p.cap = cap(s) 391 p.len = len(s) 392 393 defer func(gp *g) { 394 // Decrease the length of the slice by one, safely. 395 p := (*slice)(unsafe.Pointer(&gp.cgoCtxt)) 396 p.len-- 397 }(gp) 398 } 399 400 if gp.m.ncgo == 0 { 401 // The C call to Go came from a thread not currently running 402 // any Go. In the case of -buildmode=c-archive or c-shared, 403 // this call may be coming in before package initialization 404 // is complete. Wait until it is. 405 <-main_init_done 406 } 407 408 // Check whether the profiler needs to be turned on or off; this route to 409 // run Go code does not use runtime.execute, so bypasses the check there. 410 hz := sched.profilehz 411 if gp.m.profilehz != hz { 412 setThreadCPUProfiler(hz) 413 } 414 415 // Add entry to defer stack in case of panic. 416 restore := true 417 defer unwindm(&restore) 418 419 if raceenabled { 420 raceacquire(unsafe.Pointer(&racecgosync)) 421 } 422 423 // Invoke callback. This function is generated by cmd/cgo and 424 // will unpack the argument frame and call the Go function. 425 var cb func(frame unsafe.Pointer) 426 cbFV := funcval{uintptr(fn)} 427 *(*unsafe.Pointer)(unsafe.Pointer(&cb)) = noescape(unsafe.Pointer(&cbFV)) 428 cb(frame) 429 430 if raceenabled { 431 racereleasemerge(unsafe.Pointer(&racecgosync)) 432 } 433 434 // Do not unwind m->g0->sched.sp. 435 // Our caller, cgocallback, will do that. 436 restore = false 437 } 438 439 func unwindm(restore *bool) { 440 if *restore { 441 // Restore sp saved by cgocallback during 442 // unwind of g's stack (see comment at top of file). 443 mp := acquirem() 444 sched := &mp.g0.sched 445 sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + alignUp(sys.MinFrameSize, sys.StackAlign))) 446 447 // Do the accounting that cgocall will not have a chance to do 448 // during an unwind. 449 // 450 // In the case where a Go call originates from C, ncgo is 0 451 // and there is no matching cgocall to end. 452 if mp.ncgo > 0 { 453 mp.incgo = false 454 mp.ncgo-- 455 osPreemptExtExit(mp) 456 } 457 458 // Undo the call to lockOSThread in cgocallbackg, only on the 459 // panicking path. In normal return case cgocallbackg will call 460 // unlockOSThread, ensuring no preemption point after the unlock. 461 // Here we don't need to worry about preemption, because we're 462 // panicking out of the callback and unwinding the g0 stack, 463 // instead of reentering cgo (which requires the same thread). 464 unlockOSThread() 465 466 releasem(mp) 467 } 468 } 469 470 // called from assembly. 471 func badcgocallback() { 472 throw("misaligned stack in cgocallback") 473 } 474 475 // called from (incomplete) assembly. 476 func cgounimpl() { 477 throw("cgo not implemented") 478 } 479 480 var racecgosync uint64 // represents possible synchronization in C code 481 482 // Pointer checking for cgo code. 483 484 // We want to detect all cases where a program that does not use 485 // unsafe makes a cgo call passing a Go pointer to memory that 486 // contains an unpinned Go pointer. Here a Go pointer is defined as a 487 // pointer to memory allocated by the Go runtime. Programs that use 488 // unsafe can evade this restriction easily, so we don't try to catch 489 // them. The cgo program will rewrite all possibly bad pointer 490 // arguments to call cgoCheckPointer, where we can catch cases of a Go 491 // pointer pointing to an unpinned Go pointer. 492 493 // Complicating matters, taking the address of a slice or array 494 // element permits the C program to access all elements of the slice 495 // or array. In that case we will see a pointer to a single element, 496 // but we need to check the entire data structure. 497 498 // The cgoCheckPointer call takes additional arguments indicating that 499 // it was called on an address expression. An additional argument of 500 // true means that it only needs to check a single element. An 501 // additional argument of a slice or array means that it needs to 502 // check the entire slice/array, but nothing else. Otherwise, the 503 // pointer could be anything, and we check the entire heap object, 504 // which is conservative but safe. 505 506 // When and if we implement a moving garbage collector, 507 // cgoCheckPointer will pin the pointer for the duration of the cgo 508 // call. (This is necessary but not sufficient; the cgo program will 509 // also have to change to pin Go pointers that cannot point to Go 510 // pointers.) 511 512 // cgoCheckPointer checks if the argument contains a Go pointer that 513 // points to an unpinned Go pointer, and panics if it does. 514 func cgoCheckPointer(ptr any, arg any) { 515 if !goexperiment.CgoCheck2 && debug.cgocheck == 0 { 516 return 517 } 518 519 ep := efaceOf(&ptr) 520 t := ep._type 521 522 top := true 523 if arg != nil && (t.Kind_&abi.KindMask == abi.Pointer || t.Kind_&abi.KindMask == abi.UnsafePointer) { 524 p := ep.data 525 if t.Kind_&abi.KindDirectIface == 0 { 526 p = *(*unsafe.Pointer)(p) 527 } 528 if p == nil || !cgoIsGoPointer(p) { 529 return 530 } 531 aep := efaceOf(&arg) 532 switch aep._type.Kind_ & abi.KindMask { 533 case abi.Bool: 534 if t.Kind_&abi.KindMask == abi.UnsafePointer { 535 // We don't know the type of the element. 536 break 537 } 538 pt := (*ptrtype)(unsafe.Pointer(t)) 539 cgoCheckArg(pt.Elem, p, true, false, cgoCheckPointerFail) 540 return 541 case abi.Slice: 542 // Check the slice rather than the pointer. 543 ep = aep 544 t = ep._type 545 case abi.Array: 546 // Check the array rather than the pointer. 547 // Pass top as false since we have a pointer 548 // to the array. 549 ep = aep 550 t = ep._type 551 top = false 552 default: 553 throw("can't happen") 554 } 555 } 556 557 cgoCheckArg(t, ep.data, t.Kind_&abi.KindDirectIface == 0, top, cgoCheckPointerFail) 558 } 559 560 const cgoCheckPointerFail = "cgo argument has Go pointer to unpinned Go pointer" 561 const cgoResultFail = "cgo result is unpinned Go pointer or points to unpinned Go pointer" 562 563 // cgoCheckArg is the real work of cgoCheckPointer. The argument p 564 // is either a pointer to the value (of type t), or the value itself, 565 // depending on indir. The top parameter is whether we are at the top 566 // level, where Go pointers are allowed. Go pointers to pinned objects are 567 // allowed as long as they don't reference other unpinned pointers. 568 func cgoCheckArg(t *_type, p unsafe.Pointer, indir, top bool, msg string) { 569 if !t.Pointers() || p == nil { 570 // If the type has no pointers there is nothing to do. 571 return 572 } 573 574 switch t.Kind_ & abi.KindMask { 575 default: 576 throw("can't happen") 577 case abi.Array: 578 at := (*arraytype)(unsafe.Pointer(t)) 579 if !indir { 580 if at.Len != 1 { 581 throw("can't happen") 582 } 583 cgoCheckArg(at.Elem, p, at.Elem.Kind_&abi.KindDirectIface == 0, top, msg) 584 return 585 } 586 for i := uintptr(0); i < at.Len; i++ { 587 cgoCheckArg(at.Elem, p, true, top, msg) 588 p = add(p, at.Elem.Size_) 589 } 590 case abi.Chan, abi.Map: 591 // These types contain internal pointers that will 592 // always be allocated in the Go heap. It's never OK 593 // to pass them to C. 594 panic(errorString(msg)) 595 case abi.Func: 596 if indir { 597 p = *(*unsafe.Pointer)(p) 598 } 599 if !cgoIsGoPointer(p) { 600 return 601 } 602 panic(errorString(msg)) 603 case abi.Interface: 604 it := *(**_type)(p) 605 if it == nil { 606 return 607 } 608 // A type known at compile time is OK since it's 609 // constant. A type not known at compile time will be 610 // in the heap and will not be OK. 611 if inheap(uintptr(unsafe.Pointer(it))) { 612 panic(errorString(msg)) 613 } 614 p = *(*unsafe.Pointer)(add(p, goarch.PtrSize)) 615 if !cgoIsGoPointer(p) { 616 return 617 } 618 if !top && !isPinned(p) { 619 panic(errorString(msg)) 620 } 621 cgoCheckArg(it, p, it.Kind_&abi.KindDirectIface == 0, false, msg) 622 case abi.Slice: 623 st := (*slicetype)(unsafe.Pointer(t)) 624 s := (*slice)(p) 625 p = s.array 626 if p == nil || !cgoIsGoPointer(p) { 627 return 628 } 629 if !top && !isPinned(p) { 630 panic(errorString(msg)) 631 } 632 if !st.Elem.Pointers() { 633 return 634 } 635 for i := 0; i < s.cap; i++ { 636 cgoCheckArg(st.Elem, p, true, false, msg) 637 p = add(p, st.Elem.Size_) 638 } 639 case abi.String: 640 ss := (*stringStruct)(p) 641 if !cgoIsGoPointer(ss.str) { 642 return 643 } 644 if !top && !isPinned(ss.str) { 645 panic(errorString(msg)) 646 } 647 case abi.Struct: 648 st := (*structtype)(unsafe.Pointer(t)) 649 if !indir { 650 if len(st.Fields) != 1 { 651 throw("can't happen") 652 } 653 cgoCheckArg(st.Fields[0].Typ, p, st.Fields[0].Typ.Kind_&abi.KindDirectIface == 0, top, msg) 654 return 655 } 656 for _, f := range st.Fields { 657 if !f.Typ.Pointers() { 658 continue 659 } 660 cgoCheckArg(f.Typ, add(p, f.Offset), true, top, msg) 661 } 662 case abi.Pointer, abi.UnsafePointer: 663 if indir { 664 p = *(*unsafe.Pointer)(p) 665 if p == nil { 666 return 667 } 668 } 669 670 if !cgoIsGoPointer(p) { 671 return 672 } 673 if !top && !isPinned(p) { 674 panic(errorString(msg)) 675 } 676 677 cgoCheckUnknownPointer(p, msg) 678 } 679 } 680 681 // cgoCheckUnknownPointer is called for an arbitrary pointer into Go 682 // memory. It checks whether that Go memory contains any other 683 // pointer into unpinned Go memory. If it does, we panic. 684 // The return values are unused but useful to see in panic tracebacks. 685 func cgoCheckUnknownPointer(p unsafe.Pointer, msg string) (base, i uintptr) { 686 if inheap(uintptr(p)) { 687 b, span, _ := findObject(uintptr(p), 0, 0) 688 base = b 689 if base == 0 { 690 return 691 } 692 tp := span.typePointersOfUnchecked(base) 693 for { 694 var addr uintptr 695 if tp, addr = tp.next(base + span.elemsize); addr == 0 { 696 break 697 } 698 pp := *(*unsafe.Pointer)(unsafe.Pointer(addr)) 699 if cgoIsGoPointer(pp) && !isPinned(pp) { 700 panic(errorString(msg)) 701 } 702 } 703 return 704 } 705 706 for _, datap := range activeModules() { 707 if cgoInRange(p, datap.data, datap.edata) || cgoInRange(p, datap.bss, datap.ebss) { 708 // We have no way to know the size of the object. 709 // We have to assume that it might contain a pointer. 710 panic(errorString(msg)) 711 } 712 // In the text or noptr sections, we know that the 713 // pointer does not point to a Go pointer. 714 } 715 716 return 717 } 718 719 // cgoIsGoPointer reports whether the pointer is a Go pointer--a 720 // pointer to Go memory. We only care about Go memory that might 721 // contain pointers. 722 // 723 //go:nosplit 724 //go:nowritebarrierrec 725 func cgoIsGoPointer(p unsafe.Pointer) bool { 726 if p == nil { 727 return false 728 } 729 730 if inHeapOrStack(uintptr(p)) { 731 return true 732 } 733 734 for _, datap := range activeModules() { 735 if cgoInRange(p, datap.data, datap.edata) || cgoInRange(p, datap.bss, datap.ebss) { 736 return true 737 } 738 } 739 740 return false 741 } 742 743 // cgoInRange reports whether p is between start and end. 744 // 745 //go:nosplit 746 //go:nowritebarrierrec 747 func cgoInRange(p unsafe.Pointer, start, end uintptr) bool { 748 return start <= uintptr(p) && uintptr(p) < end 749 } 750 751 // cgoCheckResult is called to check the result parameter of an 752 // exported Go function. It panics if the result is or contains any 753 // other pointer into unpinned Go memory. 754 func cgoCheckResult(val any) { 755 if !goexperiment.CgoCheck2 && debug.cgocheck == 0 { 756 return 757 } 758 759 ep := efaceOf(&val) 760 t := ep._type 761 cgoCheckArg(t, ep.data, t.Kind_&abi.KindDirectIface == 0, false, cgoResultFail) 762 } 763