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