github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/runtime/syscall_windows.go (about)

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