...
Run Format

Source file src/runtime/syscall_windows.go

Documentation: runtime

     1  // Copyright 2014 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  package runtime
     6  
     7  import (
     8  	"unsafe"
     9  )
    10  
    11  type callbacks struct {
    12  	lock mutex
    13  	ctxt [cb_max]*wincallbackcontext
    14  	n    int
    15  }
    16  
    17  func (c *wincallbackcontext) isCleanstack() bool {
    18  	return c.cleanstack
    19  }
    20  
    21  func (c *wincallbackcontext) setCleanstack(cleanstack bool) {
    22  	c.cleanstack = cleanstack
    23  }
    24  
    25  var (
    26  	cbs     callbacks
    27  	cbctxts **wincallbackcontext = &cbs.ctxt[0] // to simplify access to cbs.ctxt in sys_windows_*.s
    28  
    29  	callbackasm byte // type isn't really byte, it's code in runtime
    30  )
    31  
    32  // callbackasmAddr returns address of runtime.callbackasm
    33  // function adjusted by i.
    34  // runtime.callbackasm is just a series of CALL instructions
    35  // (each is 5 bytes long), and we want callback to arrive at
    36  // correspondent call instruction instead of start of
    37  // runtime.callbackasm.
    38  func callbackasmAddr(i int) uintptr {
    39  	return uintptr(add(unsafe.Pointer(&callbackasm), uintptr(i*5)))
    40  }
    41  
    42  //go:linkname compileCallback syscall.compileCallback
    43  func compileCallback(fn eface, cleanstack bool) (code uintptr) {
    44  	if fn._type == nil || (fn._type.kind&kindMask) != kindFunc {
    45  		panic("compileCallback: expected function with one uintptr-sized result")
    46  	}
    47  	ft := (*functype)(unsafe.Pointer(fn._type))
    48  	if len(ft.out()) != 1 {
    49  		panic("compileCallback: expected function with one uintptr-sized result")
    50  	}
    51  	uintptrSize := unsafe.Sizeof(uintptr(0))
    52  	if ft.out()[0].size != uintptrSize {
    53  		panic("compileCallback: expected function with one uintptr-sized result")
    54  	}
    55  	argsize := uintptr(0)
    56  	for _, t := range ft.in() {
    57  		if t.size > uintptrSize {
    58  			panic("compileCallback: argument size is larger than uintptr")
    59  		}
    60  		argsize += uintptrSize
    61  	}
    62  
    63  	lock(&cbs.lock)
    64  	defer unlock(&cbs.lock)
    65  
    66  	n := cbs.n
    67  	for i := 0; i < n; i++ {
    68  		if cbs.ctxt[i].gobody == fn.data && cbs.ctxt[i].isCleanstack() == cleanstack {
    69  			return callbackasmAddr(i)
    70  		}
    71  	}
    72  	if n >= cb_max {
    73  		throw("too many callback functions")
    74  	}
    75  
    76  	c := new(wincallbackcontext)
    77  	c.gobody = fn.data
    78  	c.argsize = argsize
    79  	c.setCleanstack(cleanstack)
    80  	if cleanstack && argsize != 0 {
    81  		c.restorestack = argsize
    82  	} else {
    83  		c.restorestack = 0
    84  	}
    85  	cbs.ctxt[n] = c
    86  	cbs.n++
    87  
    88  	return callbackasmAddr(n)
    89  }
    90  
    91  const _LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800
    92  
    93  //go:linkname syscall_loadsystemlibrary syscall.loadsystemlibrary
    94  //go:nosplit
    95  func syscall_loadsystemlibrary(filename *uint16) (handle, err uintptr) {
    96  	lockOSThread()
    97  	defer unlockOSThread()
    98  	c := &getg().m.syscall
    99  
   100  	if useLoadLibraryEx {
   101  		c.fn = getLoadLibraryEx()
   102  		c.n = 3
   103  		args := struct {
   104  			lpFileName *uint16
   105  			hFile      uintptr // always 0
   106  			flags      uint32
   107  		}{filename, 0, _LOAD_LIBRARY_SEARCH_SYSTEM32}
   108  		c.args = uintptr(noescape(unsafe.Pointer(&args)))
   109  	} else {
   110  		// User doesn't have KB2533623 installed. The caller
   111  		// wanted to only load the filename DLL from the
   112  		// System32 directory but that facility doesn't exist,
   113  		// so just load it the normal way. This is a potential
   114  		// security risk, but so is not installing security
   115  		// updates.
   116  		c.fn = getLoadLibrary()
   117  		c.n = 1
   118  		c.args = uintptr(noescape(unsafe.Pointer(&filename)))
   119  	}
   120  
   121  	cgocall(asmstdcallAddr, unsafe.Pointer(c))
   122  	handle = c.r1
   123  	if handle == 0 {
   124  		err = c.err
   125  	}
   126  	return
   127  }
   128  
   129  //go:linkname syscall_loadlibrary syscall.loadlibrary
   130  //go:nosplit
   131  func syscall_loadlibrary(filename *uint16) (handle, err uintptr) {
   132  	lockOSThread()
   133  	defer unlockOSThread()
   134  	c := &getg().m.syscall
   135  	c.fn = getLoadLibrary()
   136  	c.n = 1
   137  	c.args = uintptr(noescape(unsafe.Pointer(&filename)))
   138  	cgocall(asmstdcallAddr, unsafe.Pointer(c))
   139  	handle = c.r1
   140  	if handle == 0 {
   141  		err = c.err
   142  	}
   143  	return
   144  }
   145  
   146  //go:linkname syscall_getprocaddress syscall.getprocaddress
   147  //go:nosplit
   148  func syscall_getprocaddress(handle uintptr, procname *byte) (outhandle, err uintptr) {
   149  	lockOSThread()
   150  	defer unlockOSThread()
   151  	c := &getg().m.syscall
   152  	c.fn = getGetProcAddress()
   153  	c.n = 2
   154  	c.args = uintptr(noescape(unsafe.Pointer(&handle)))
   155  	cgocall(asmstdcallAddr, unsafe.Pointer(c))
   156  	outhandle = c.r1
   157  	if outhandle == 0 {
   158  		err = c.err
   159  	}
   160  	return
   161  }
   162  
   163  //go:linkname syscall_Syscall syscall.Syscall
   164  //go:nosplit
   165  func syscall_Syscall(fn, nargs, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
   166  	lockOSThread()
   167  	defer unlockOSThread()
   168  	c := &getg().m.syscall
   169  	c.fn = fn
   170  	c.n = nargs
   171  	c.args = uintptr(noescape(unsafe.Pointer(&a1)))
   172  	cgocall(asmstdcallAddr, unsafe.Pointer(c))
   173  	return c.r1, c.r2, c.err
   174  }
   175  
   176  //go:linkname syscall_Syscall6 syscall.Syscall6
   177  //go:nosplit
   178  func syscall_Syscall6(fn, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
   179  	lockOSThread()
   180  	defer unlockOSThread()
   181  	c := &getg().m.syscall
   182  	c.fn = fn
   183  	c.n = nargs
   184  	c.args = uintptr(noescape(unsafe.Pointer(&a1)))
   185  	cgocall(asmstdcallAddr, unsafe.Pointer(c))
   186  	return c.r1, c.r2, c.err
   187  }
   188  
   189  //go:linkname syscall_Syscall9 syscall.Syscall9
   190  //go:nosplit
   191  func syscall_Syscall9(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2, err uintptr) {
   192  	lockOSThread()
   193  	defer unlockOSThread()
   194  	c := &getg().m.syscall
   195  	c.fn = fn
   196  	c.n = nargs
   197  	c.args = uintptr(noescape(unsafe.Pointer(&a1)))
   198  	cgocall(asmstdcallAddr, unsafe.Pointer(c))
   199  	return c.r1, c.r2, c.err
   200  }
   201  
   202  //go:linkname syscall_Syscall12 syscall.Syscall12
   203  //go:nosplit
   204  func syscall_Syscall12(fn, nargs, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 uintptr) (r1, r2, err uintptr) {
   205  	lockOSThread()
   206  	defer unlockOSThread()
   207  	c := &getg().m.syscall
   208  	c.fn = fn
   209  	c.n = nargs
   210  	c.args = uintptr(noescape(unsafe.Pointer(&a1)))
   211  	cgocall(asmstdcallAddr, unsafe.Pointer(c))
   212  	return c.r1, c.r2, c.err
   213  }
   214  
   215  //go:linkname syscall_Syscall15 syscall.Syscall15
   216  //go:nosplit
   217  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) {
   218  	lockOSThread()
   219  	defer unlockOSThread()
   220  	c := &getg().m.syscall
   221  	c.fn = fn
   222  	c.n = nargs
   223  	c.args = uintptr(noescape(unsafe.Pointer(&a1)))
   224  	cgocall(asmstdcallAddr, unsafe.Pointer(c))
   225  	return c.r1, c.r2, c.err
   226  }
   227  

View as plain text