github.com/undefinedlabs/go-mpatch@v1.0.8-0.20230904093002-fbac8a0d7853/patcher_arm64.go (about)

     1  //go:build arm64
     2  // +build arm64
     3  
     4  package mpatch
     5  
     6  import "unsafe"
     7  
     8  // Code from: https://github.com/agiledragon/gomonkey/blob/master/jmp_arm64.go
     9  
    10  // Gets the jump function rewrite bytes
    11  //
    12  //go:nosplit
    13  func getJumpFuncBytes(to unsafe.Pointer) ([]byte, error) {
    14  	res := make([]byte, 0, 24)
    15  	d0d1 := uintptr(to) & 0xFFFF
    16  	d2d3 := uintptr(to) >> 16 & 0xFFFF
    17  	d4d5 := uintptr(to) >> 32 & 0xFFFF
    18  	d6d7 := uintptr(to) >> 48 & 0xFFFF
    19  
    20  	res = append(res, movImm(0b10, 0, d0d1)...)          // MOVZ x26, double[16:0]
    21  	res = append(res, movImm(0b11, 1, d2d3)...)          // MOVK x26, double[32:16]
    22  	res = append(res, movImm(0b11, 2, d4d5)...)          // MOVK x26, double[48:32]
    23  	res = append(res, movImm(0b11, 3, d6d7)...)          // MOVK x26, double[64:48]
    24  	res = append(res, []byte{0x4A, 0x03, 0x40, 0xF9}...) // LDR x10, [x26]
    25  	res = append(res, []byte{0x40, 0x01, 0x1F, 0xD6}...) // BR x10
    26  
    27  	return res, nil
    28  }
    29  
    30  func movImm(opc, shift int, val uintptr) []byte {
    31  	var m uint32 = 26          // rd
    32  	m |= uint32(val) << 5      // imm16
    33  	m |= uint32(shift&3) << 21 // hw
    34  	m |= 0b100101 << 23        // const
    35  	m |= uint32(opc&0x3) << 29 // opc
    36  	m |= 0b1 << 31             // sf
    37  
    38  	res := make([]byte, 4)
    39  	*(*uint32)(unsafe.Pointer(&res[0])) = m
    40  
    41  	return res
    42  }