Source file
src/runtime/syscall_windows.go
1
2
3
4
5 package runtime
6
7 import (
8 "internal/abi"
9 "internal/goarch"
10 "unsafe"
11 )
12
13
14 var cbs struct {
15 lock mutex
16 ctxt [cb_max]winCallback
17 index map[winCallbackKey]int
18 n int
19 }
20
21 func cbsLock() {
22 lock(&cbs.lock)
23
24
25
26
27 if raceenabled && mainStarted {
28 raceacquire(unsafe.Pointer(&cbs.lock))
29 }
30 }
31
32 func cbsUnlock() {
33 if raceenabled && mainStarted {
34 racerelease(unsafe.Pointer(&cbs.lock))
35 }
36 unlock(&cbs.lock)
37 }
38
39
40 type winCallback struct {
41 fn *funcval
42 retPop uintptr
43 abiMap abiDesc
44 }
45
46
47 type abiPartKind int
48
49 const (
50 abiPartBad abiPartKind = iota
51 abiPartStack
52 abiPartReg
53 )
54
55
56 type abiPart struct {
57 kind abiPartKind
58 srcStackOffset uintptr
59 dstStackOffset uintptr
60 dstRegister int
61 len uintptr
62 }
63
64 func (a *abiPart) tryMerge(b abiPart) bool {
65 if a.kind != abiPartStack || b.kind != abiPartStack {
66 return false
67 }
68 if a.srcStackOffset+a.len == b.srcStackOffset && a.dstStackOffset+a.len == b.dstStackOffset {
69 a.len += b.len
70 return true
71 }
72 return false
73 }
74
75
76
77
78
79
80 type abiDesc struct {
81 parts []abiPart
82
83 srcStackSize uintptr
84 dstStackSize uintptr
85 dstSpill uintptr
86 dstRegisters int
87
88
89
90 retOffset uintptr
91 }
92
93 func (p *abiDesc) assignArg(t *_type) {
94 if t.size > goarch.PtrSize {
95
96
97
98
99
100
101
102
103
104 panic("compileCallback: argument size is larger than uintptr")
105 }
106 if k := t.kind & kindMask; GOARCH != "386" && (k == kindFloat32 || k == kindFloat64) {
107
108
109
110
111
112
113
114 panic("compileCallback: float arguments not supported")
115 }
116
117 if t.size == 0 {
118
119 p.dstStackSize = alignUp(p.dstStackSize, uintptr(t.align))
120 return
121 }
122
123
124
125
126
127
128
129
130
131 oldParts := p.parts
132 if p.tryRegAssignArg(t, 0) {
133
134
135
136
137 p.dstSpill = alignUp(p.dstSpill, uintptr(t.align))
138 p.dstSpill += t.size
139 } else {
140
141
142 p.parts = oldParts
143
144
145 p.dstStackSize = alignUp(p.dstStackSize, uintptr(t.align))
146
147
148
149
150
151 part := abiPart{
152 kind: abiPartStack,
153 srcStackOffset: p.srcStackSize,
154 dstStackOffset: p.dstStackSize,
155 len: t.size,
156 }
157
158 if len(p.parts) == 0 || !p.parts[len(p.parts)-1].tryMerge(part) {
159 p.parts = append(p.parts, part)
160 }
161
162 p.dstStackSize += t.size
163 }
164
165
166
167 p.srcStackSize += goarch.PtrSize
168 }
169
170
171
172
173
174
175
176 func (p *abiDesc) tryRegAssignArg(t *_type, offset uintptr) bool {
177 switch k := t.kind & kindMask; k {
178 case kindBool, kindInt, kindInt8, kindInt16, kindInt32, kindUint, kindUint8, kindUint16, kindUint32, kindUintptr, kindPtr, kindUnsafePointer:
179
180 return p.assignReg(t.size, offset)
181 case kindInt64, kindUint64:
182
183 if goarch.PtrSize == 8 {
184 return p.assignReg(t.size, offset)
185 }
186 case kindArray:
187 at := (*arraytype)(unsafe.Pointer(t))
188 if at.len == 1 {
189 return p.tryRegAssignArg(at.elem, offset)
190 }
191 case kindStruct:
192 st := (*structtype)(unsafe.Pointer(t))
193 for i := range st.fields {
194 f := &st.fields[i]
195 if !p.tryRegAssignArg(f.typ, offset+f.offset) {
196 return false
197 }
198 }
199 return true
200 }
201
202
203 panic("compileCallabck: type " + t.string() + " is currently not supported for use in system callbacks")
204 }
205
206
207
208
209
210
211 func (p *abiDesc) assignReg(size, offset uintptr) bool {
212 if p.dstRegisters >= intArgRegs {
213 return false
214 }
215 p.parts = append(p.parts, abiPart{
216 kind: abiPartReg,
217 srcStackOffset: p.srcStackSize + offset,
218 dstRegister: p.dstRegisters,
219 len: size,
220 })
221 p.dstRegisters++
222 return true
223 }
224
225 type winCallbackKey struct {
226 fn *funcval
227 cdecl bool
228 }
229
230 func callbackasm()
231
232
233
234
235
236
237
238
239
240
241 func callbackasmAddr(i int) uintptr {
242 var entrySize int
243 switch GOARCH {
244 default:
245 panic("unsupported architecture")
246 case "386", "amd64":
247 entrySize = 5
248 case "arm", "arm64":
249
250
251 entrySize = 8
252 }
253 return abi.FuncPCABI0(callbackasm) + uintptr(i*entrySize)
254 }
255
256 const callbackMaxFrame = 64 * goarch.PtrSize
257
258
259
260
261
262
263
264
265
266 func compileCallback(fn eface, cdecl bool) (code uintptr) {
267 if GOARCH != "386" {
268
269 cdecl = false
270 }
271
272 if fn._type == nil || (fn._type.kind&kindMask) != kindFunc {
273 panic("compileCallback: expected function with one uintptr-sized result")
274 }
275 ft := (*functype)(unsafe.Pointer(fn._type))
276
277
278 var abiMap abiDesc
279 for _, t := range ft.in() {
280 abiMap.assignArg(t)
281 }
282
283
284 abiMap.dstStackSize = alignUp(abiMap.dstStackSize, goarch.PtrSize)
285 abiMap.retOffset = abiMap.dstStackSize
286
287 if len(ft.out()) != 1 {
288 panic("compileCallback: expected function with one uintptr-sized result")
289 }
290 if ft.out()[0].size != goarch.PtrSize {
291 panic("compileCallback: expected function with one uintptr-sized result")
292 }
293 if k := ft.out()[0].kind & kindMask; k == kindFloat32 || k == kindFloat64 {
294
295
296
297 panic("compileCallback: float results not supported")
298 }
299 if intArgRegs == 0 {
300
301
302
303 abiMap.dstStackSize += goarch.PtrSize
304 }
305
306
307
308 frameSize := alignUp(abiMap.dstStackSize, goarch.PtrSize)
309 frameSize += abiMap.dstSpill
310 if frameSize > callbackMaxFrame {
311 panic("compileCallback: function argument frame too large")
312 }
313
314
315
316 var retPop uintptr
317 if cdecl {
318 retPop = abiMap.srcStackSize
319 }
320
321 key := winCallbackKey{(*funcval)(fn.data), cdecl}
322
323 cbsLock()
324
325
326 if n, ok := cbs.index[key]; ok {
327 cbsUnlock()
328 return callbackasmAddr(n)
329 }
330
331
332 if cbs.index == nil {
333 cbs.index = make(map[winCallbackKey]int)
334 }
335 n := cbs.n
336 if n >= len(cbs.ctxt) {
337 cbsUnlock()
338 throw("too many callback functions")
339 }
340 c := winCallback{key.fn, retPop, abiMap}
341 cbs.ctxt[n] = c
342 cbs.index[key] = n
343 cbs.n++
344
345 cbsUnlock()
346 return callbackasmAddr(n)
347 }
348
349 type callbackArgs struct {
350 index uintptr
351
352
353
354
355
356
357
358
359
360
361
362 args unsafe.Pointer
363
364 result uintptr
365 retPop uintptr
366 }
367
368
369 func callbackWrap(a *callbackArgs) {
370 c := cbs.ctxt[a.index]
371 a.retPop = c.retPop
372
373
374 var regs abi.RegArgs
375 var frame [callbackMaxFrame]byte
376 goArgs := unsafe.Pointer(&frame)
377 for _, part := range c.abiMap.parts {
378 switch part.kind {
379 case abiPartStack:
380 memmove(add(goArgs, part.dstStackOffset), add(a.args, part.srcStackOffset), part.len)
381 case abiPartReg:
382 goReg := unsafe.Pointer(®s.Ints[part.dstRegister])
383 memmove(goReg, add(a.args, part.srcStackOffset), part.len)
384 default:
385 panic("bad ABI description")
386 }
387 }
388
389
390
391 frameSize := alignUp(c.abiMap.dstStackSize, goarch.PtrSize)
392 frameSize += c.abiMap.dstSpill
393
394
395
396 reflectcall(nil, unsafe.Pointer(c.fn), noescape(goArgs), uint32(c.abiMap.dstStackSize), uint32(c.abiMap.retOffset), uint32(frameSize), ®s)
397
398
399
400
401
402
403 if c.abiMap.dstStackSize != c.abiMap.retOffset {
404 a.result = *(*uintptr)(unsafe.Pointer(&frame[c.abiMap.retOffset]))
405 } else {
406 var zero int
407
408
409
410 a.result = regs.Ints[zero]
411 }
412 }
413
414 const _LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800
415
416
417
418
419
420
421
422
423
424 func syscall_loadsystemlibrary(filename *uint16, absoluteFilepath *uint16) (handle, err uintptr) {
425 lockOSThread()
426 c := &getg().m.syscall
427
428 if useLoadLibraryEx {
429 c.fn = getLoadLibraryEx()
430 c.n = 3
431 args := struct {
432 lpFileName *uint16
433 hFile uintptr
434 flags uint32
435 }{filename, 0, _LOAD_LIBRARY_SEARCH_SYSTEM32}
436 c.args = uintptr(noescape(unsafe.Pointer(&args)))
437 } else {
438 c.fn = getLoadLibrary()
439 c.n = 1
440 c.args = uintptr(noescape(unsafe.Pointer(&absoluteFilepath)))
441 }
442
443 cgocall(asmstdcallAddr, unsafe.Pointer(c))
444 KeepAlive(filename)
445 KeepAlive(absoluteFilepath)
446 handle = c.r1
447 if handle == 0 {
448 err = c.err
449 }
450 unlockOSThread()
451 return
452 }
453
454
455
456
457 func syscall_loadlibrary(filename *uint16) (handle, err uintptr) {
458 lockOSThread()
459 defer unlockOSThread()
460 c := &getg().m.syscall
461 c.fn = getLoadLibrary()
462 c.n = 1
463 c.args = uintptr(noescape(unsafe.Pointer(&filename)))
464 cgocall(asmstdcallAddr, unsafe.Pointer(c))
465 KeepAlive(filename)
466 handle = c.r1
467 if handle == 0 {
468 err = c.err
469 }
470 return
471 }
472
473
474
475
476 func syscall_getprocaddress(handle uintptr, procname *byte) (outhandle, err uintptr) {
477 lockOSThread()
478 defer unlockOSThread()
479 c := &getg().m.syscall
480 c.fn = getGetProcAddress()
481 c.n = 2
482 c.args = uintptr(noescape(unsafe.Pointer(&handle)))
483 cgocall(asmstdcallAddr, unsafe.Pointer(c))
484 KeepAlive(procname)
485 outhandle = c.r1
486 if outhandle == 0 {
487 err = c.err
488 }
489 return
490 }
491
492
493
494 func syscall_Syscall(fn, nargs, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
495 return syscall_SyscallN(fn, a1, a2, a3)
496 }
497
498
499
500 func syscall_Syscall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
501 return syscall_SyscallN(fn, a1, a2, a3, a4, a5, a6)
502 }
503
504
505
506 func syscall_Syscall9(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
507 return syscall_SyscallN(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9)
508 }
509
510
511
512 func syscall_Syscall12(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 uintptr) (r1, r2, err uintptr) {
513 return syscall_SyscallN(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12)
514 }
515
516
517
518 func syscall_Syscall15(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 uintptr) (r1, r2, err uintptr) {
519 return syscall_SyscallN(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15)
520 }
521
522
523
524 func syscall_Syscall18(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18 uintptr) (r1, r2, err uintptr) {
525 return syscall_SyscallN(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18)
526 }
527
528
529
530
531
532
533 const maxArgs = 42
534
535
536
537 func syscall_SyscallN(trap uintptr, args ...uintptr) (r1, r2, err uintptr) {
538 nargs := len(args)
539
540
541
542 var tmp [4]uintptr
543 switch {
544 case nargs < 4:
545 copy(tmp[:], args)
546 args = tmp[:]
547 case nargs > maxArgs:
548 panic("runtime: SyscallN has too many arguments")
549 }
550
551 lockOSThread()
552 defer unlockOSThread()
553 c := &getg().m.syscall
554 c.fn = trap
555 c.n = uintptr(nargs)
556 c.args = uintptr(noescape(unsafe.Pointer(&args[0])))
557 cgocall(asmstdcallAddr, unsafe.Pointer(c))
558 return c.r1, c.r2, c.err
559 }
560
View as plain text