loader_windows.go (3033B)
1 //go:build windows 2 // +build windows 3 4 /* 5 * Copyright 2021 ByteDance Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 */ 19 20 package loader 21 22 import ( 23 `fmt` 24 `os` 25 `reflect` 26 `syscall` 27 `unsafe` 28 ) 29 30 const ( 31 MEM_COMMIT = 0x00001000 32 MEM_RESERVE = 0x00002000 33 ) 34 35 var ( 36 libKernel32 = syscall.NewLazyDLL("KERNEL32.DLL") 37 libKernel32_VirtualAlloc = libKernel32.NewProc("VirtualAlloc") 38 libKernel32_VirtualProtect = libKernel32.NewProc("VirtualProtect") 39 ) 40 41 type Loader []byte 42 type Function unsafe.Pointer 43 44 func (self Loader) Load(fn string, fp int, args int, argPtrs []bool, localPtrs []bool) (f Function) { 45 p := os.Getpagesize() 46 n := (((len(self) - 1) / p) + 1) * p 47 48 /* register the function */ 49 m := mmap(n) 50 v := fmt.Sprintf("runtime.__%s_%x", fn, m) 51 52 registerFunction(v, m, uintptr(n), fp, args, uintptr(len(self)), argPtrs, localPtrs) 53 54 /* reference as a slice */ 55 s := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader { 56 Data : m, 57 Cap : n, 58 Len : len(self), 59 })) 60 61 /* copy the machine code, and make it executable */ 62 copy(s, self) 63 mprotect(m, n) 64 return Function(&m) 65 } 66 67 func mmap(nb int) uintptr { 68 addr, err := winapi_VirtualAlloc(0, nb, MEM_COMMIT|MEM_RESERVE, syscall.PAGE_READWRITE) 69 if err != nil { 70 panic(err) 71 } 72 return addr 73 } 74 75 func mprotect(p uintptr, nb int) (oldProtect int) { 76 err := winapi_VirtualProtect(p, nb, syscall.PAGE_EXECUTE_READ, &oldProtect) 77 if err != nil { 78 panic(err) 79 } 80 return 81 } 82 83 // winapi_VirtualAlloc allocate memory 84 // Doc: https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc 85 func winapi_VirtualAlloc(lpAddr uintptr, dwSize int, flAllocationType int, flProtect int) (uintptr, error) { 86 r1, _, err := libKernel32_VirtualAlloc.Call( 87 lpAddr, 88 uintptr(dwSize), 89 uintptr(flAllocationType), 90 uintptr(flProtect), 91 ) 92 if r1 == 0 { 93 return 0, err 94 } 95 return r1, nil 96 } 97 98 // winapi_VirtualProtect change memory protection 99 // Doc: https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotect 100 func winapi_VirtualProtect(lpAddr uintptr, dwSize int, flNewProtect int, lpflOldProtect *int) error { 101 r1, _, err := libKernel32_VirtualProtect.Call( 102 lpAddr, 103 uintptr(dwSize), 104 uintptr(flNewProtect), 105 uintptr(unsafe.Pointer(lpflOldProtect)), 106 ) 107 if r1 == 0 { 108 return err 109 } 110 return nil 111 }