github.com/go-darwin/sys@v0.0.0-20220510002607-68fd01f054ca/ccall.go (about) 1 // Copyright 2021 The Go Darwin Authors 2 // SPDX-License-Identifier: BSD-3-Clause 3 4 //go:build darwin && amd64 5 // +build darwin,amd64 6 7 package sys 8 9 import ( 10 "bytes" 11 "unsafe" 12 13 "github.com/go-darwin/sys/unsafeheader" 14 ) 15 16 //go:linkname ccall syscall.syscall 17 //go:noescape 18 func ccall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) 19 20 // Ccall calls a function in libc on behalf of the syscall package. 21 // 22 // syscall takes a pointer to a struct like: 23 // 24 // struct { 25 // fn uintptr 26 // a1 uintptr 27 // a2 uintptr 28 // a3 uintptr 29 // r1 uintptr 30 // r2 uintptr 31 // err uintptr 32 // } 33 // 34 // Ccall must be called on the g0 stack with the 35 // C calling convention (use libcCall). 36 // 37 // Ccall expects a 32-bit result and tests for 32-bit -1 38 // to decide there was an error. 39 // 40 //go:nosplit 41 func Ccall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { 42 return ccall(fn, a1, a2, a3) 43 } 44 45 //go:linkname ccall6 syscall.syscall6 46 //go:noescape 47 func ccall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) 48 49 // Ccall6 calls a function in libc on behalf of the syscall package. 50 // 51 // Ccall6 takes a pointer to a struct like: 52 // 53 // struct { 54 // fn uintptr 55 // a1 uintptr 56 // a2 uintptr 57 // a3 uintptr 58 // a4 uintptr 59 // a5 uintptr 60 // a6 uintptr 61 // r1 uintptr 62 // r2 uintptr 63 // err uintptr 64 // } 65 // 66 // Ccall6 must be called on the g0 stack with the 67 // C calling convention (use libcCall). 68 // 69 // Ccall6 expects a 32-bit result and tests for 32-bit -1 70 // to decide there was an error. 71 // 72 //go:nosplit 73 func Ccall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { 74 return ccall6(fn, a1, a2, a3, a4, a5, a6) 75 } 76 77 //go:linkname ccall6X syscall.syscall6X 78 //go:noescape 79 func ccall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) 80 81 // Ccall6X calls a function in libc on behalf of the syscall package. 82 // 83 // Ccall6X takes a pointer to a struct like: 84 // 85 // struct { 86 // fn uintptr 87 // a1 uintptr 88 // a2 uintptr 89 // a3 uintptr 90 // a4 uintptr 91 // a5 uintptr 92 // a6 uintptr 93 // r1 uintptr 94 // r2 uintptr 95 // err uintptr 96 // } 97 // 98 // Ccall6X must be called on the g0 stack with the 99 // C calling convention (use libcCall). 100 // 101 // Ccall6X is like syscall6 but expects a 64-bit result 102 // and tests for 64-bit -1 to decide there was an error. 103 // 104 //go:nosplit 105 func Ccall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { 106 return ccall6X(fn, a1, a2, a3, a4, a5, a6) 107 } 108 109 // Ccall9 calls a function in libc on behalf of the syscall package. 110 // 111 // Ccall9 takes a pointer to a struct like: 112 // 113 // struct { 114 // fn uintptr 115 // a1 uintptr 116 // a2 uintptr 117 // a3 uintptr 118 // a4 uintptr 119 // a5 uintptr 120 // a6 uintptr 121 // a7 uintptr 122 // a8 uintptr 123 // a9 uintptr 124 // r1 uintptr 125 // r2 uintptr 126 // err uintptr 127 // } 128 // 129 // Ccall9 must be called on the g0 stack with the 130 // C calling convention (use libcCall). 131 // 132 // Ccall9 expects a 32-bit result and tests for 32-bit -1 133 // to decide there was an error. 134 // 135 //go:linkname Ccall9 syscall.Syscall9 136 //go:nosplit 137 func Ccall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) 138 139 //go:linkname ccallPtr syscall.syscallPtr 140 //go:noescape 141 func ccallPtr(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) 142 143 // CcallPtr is like syscallX except that the libc function reports an 144 // error by returning NULL and setting errno. 145 // 146 //go:nosplit 147 func CcallPtr(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { 148 return ccallPtr(fn, a1, a2, a3) 149 } 150 151 //go:linkname rawCcall syscall.rawSyscall 152 //go:noescape 153 func rawCcall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) 154 155 // RawCcall calls a function in libc on behalf of the syscall package. 156 // 157 //go:nosplit 158 func RawCcall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { 159 return rawCcall(fn, a1, a2, a3) 160 } 161 162 //go:linkname rawSyscall6 syscall.rawSyscall6 163 //go:noescape 164 func rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) 165 166 // RawCcall6 calls a function in libc on behalf of the syscall package. 167 // 168 //go:nosplit 169 func RawCcall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { 170 return rawSyscall6(fn, a1, a2, a3, a4, a5, a6) 171 } 172 173 // RawCcall9 calls a function in libc on behalf of the syscall package. 174 // 175 //go:noescape 176 //go:nosplit 177 func RawCcall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) 178 179 // ByteSliceFromString returns a NUL-terminated slice of bytes 180 // containing the text of s. 181 func ByteSliceFromString(s string) []byte { 182 a := make([]byte, len(s)+1) 183 copy(a, s) 184 185 return a 186 } 187 188 // BytePtrFromString returns a pointer to a NUL-terminated array of 189 // bytes containing the text of s. 190 func BytePtrFromString(s string) *byte { 191 a := ByteSliceFromString(s) 192 193 return &a[0] 194 } 195 196 // ByteSliceToString returns a string form of the text represented by the slice s, with a terminating NUL and any 197 // bytes after the NUL removed. 198 func ByteSliceToString(s []byte) string { 199 if i := bytes.IndexByte(s, 0); i != -1 { 200 s = s[:i] 201 } 202 203 return string(s) 204 } 205 206 // BytePtrToString takes a pointer to a sequence of text and returns the corresponding string. 207 // If the pointer is nil, it returns the empty string. It assumes that the text sequence is terminated 208 // at a zero byte; if the zero byte is not present, the program may crash. 209 func BytePtrToString(p *byte) string { 210 if p == nil || *p == 0 { 211 return "" 212 } 213 214 // Find NUL terminator. 215 n := 0 216 for ptr := unsafe.Pointer(p); *(*byte)(ptr) != 0; n++ { 217 ptr = unsafe.Pointer(uintptr(ptr) + 1) 218 } 219 220 var b []byte 221 h := (*unsafeheader.Slice)(unsafe.Pointer(&b)) 222 h.Data = unsafe.Pointer(p) 223 h.Len = n 224 h.Cap = n 225 226 return string(b) 227 }