github.com/eh-steve/goloader@v0.0.0-20240111193454-90ff3cfdae39/mmap/mmap_darwin_arm64.go (about)

     1  //go:build darwin && arm64
     2  // +build darwin,arm64
     3  
     4  package mmap
     5  
     6  import (
     7  	"github.com/eh-steve/goloader/mmap/darwin_arm64"
     8  	"github.com/eh-steve/goloader/mprotect"
     9  
    10  	"fmt"
    11  	"os"
    12  	"reflect"
    13  	"syscall"
    14  	"unsafe"
    15  )
    16  
    17  func MakeThreadJITCodeExecutable(ptr uintptr, len int) {
    18  	var pages []byte
    19  	pageSlice := (*reflect.SliceHeader)(unsafe.Pointer(&pages))
    20  	pageSlice.Data = ptr
    21  	pageSlice.Len = len
    22  	pageSlice.Cap = len
    23  	err := mprotect.MprotectMakeExecutable(pages)
    24  	if err != nil {
    25  		panic(err)
    26  	}
    27  	darwin_arm64.MakeThreadJITCodeExecutable(ptr, len)
    28  }
    29  
    30  func Mmap(size int) ([]byte, error) {
    31  	return AcquireMapping(size, mmapCode)
    32  }
    33  
    34  func MmapData(size int) ([]byte, error) {
    35  	return AcquireMapping(size, mmapData)
    36  }
    37  
    38  func mmapCode(size int, addr uintptr) ([]byte, error) {
    39  	// darwin arm64 won't accept MAP_FIXED, but seems to take addr as a hint...
    40  	data, err := mapper.Mmap(
    41  		addr,
    42  		-1,
    43  		0,
    44  		size,
    45  		syscall.PROT_READ|syscall.PROT_WRITE, // this is not yet executable, we will mprotect it after we're finished writing to it
    46  		syscall.MAP_PRIVATE|syscall.MAP_ANON|syscall.MAP_JIT)
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  	if uintptr(unsafe.Pointer(&data[0]))-addr > 1<<24 {
    51  		defer mapper.Munmap(data)
    52  		return nil, fmt.Errorf("failed to acquire code mapping within 24 bit address of 0x%x, got %p", addr, &data[0])
    53  	}
    54  	darwin_arm64.WriteProtectDisable()
    55  	return data, err
    56  }
    57  
    58  func mmapData(size int, addr uintptr) ([]byte, error) {
    59  	// darwin arm64 won't accept MAP_FIXED, but seems to take addr as a hint...
    60  	data, err := mapper.Mmap(
    61  		addr,
    62  		-1,
    63  		0,
    64  		size,
    65  		syscall.PROT_READ|syscall.PROT_WRITE,
    66  		syscall.MAP_PRIVATE|syscall.MAP_ANON)
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  	if uintptr(unsafe.Pointer(&data[0]))-addr > 1<<24 {
    71  		defer mapper.Munmap(data)
    72  		return nil, fmt.Errorf("failed to acquire data mapping within 24 bit address of 0x%x, got %p", addr, &data[0])
    73  	}
    74  	return data, err
    75  }
    76  
    77  func Munmap(b []byte) (err error) {
    78  	err = mapper.Munmap(b)
    79  	if err != nil {
    80  		err = os.NewSyscallError("syscall.Munmap", err)
    81  	}
    82  	return
    83  }