gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }