github.com/tencent/goom@v1.0.1/internal/patch/monkey_arm64.go (about)

     1  package patch
     2  
     3  import (
     4  	"unsafe"
     5  )
     6  
     7  const (
     8  	_0b1      = 1  // _0b1
     9  	_0b10     = 2  // 0b10
    10  	_0b11     = 3  // 0b11
    11  	_0b100101 = 37 // 0b100101
    12  )
    13  
    14  // nopOpcode 空指令插入到原函数开头第一个字节, 用于判断原函数是否已经被Patch过
    15  var nopOpcode = []byte{0xD5, 0x03, 0x20, 0x1F}
    16  
    17  func jmpToFunctionValue(_, double uintptr) []byte {
    18  	//func buildJmpDirective(double uintptr) []byte {
    19  	res := make([]byte, 0, 24)
    20  	d0d1 := double & 0xFFFF
    21  	d2d3 := double >> 16 & 0xFFFF
    22  	d4d5 := double >> 32 & 0xFFFF
    23  	d6d7 := double >> 48 & 0xFFFF
    24  
    25  	res = append(res, movImm(_0b10, 0, d0d1)...)         // MOVZ x26, double[16:0]
    26  	res = append(res, movImm(_0b11, 1, d2d3)...)         // MOVK x26, double[32:16]
    27  	res = append(res, movImm(_0b11, 2, d4d5)...)         // MOVK x26, double[48:32]
    28  	res = append(res, movImm(_0b11, 3, d6d7)...)         // MOVK x26, double[64:48]
    29  	res = append(res, []byte{0x4A, 0x03, 0x40, 0xF9}...) // LDR x10, [x26]
    30  	res = append(res, []byte{0x40, 0x01, 0x1F, 0xD6}...) // BR x10
    31  
    32  	return res
    33  }
    34  
    35  func movImm(opc, shift int, val uintptr) []byte {
    36  	var m uint32 = 26          // rd
    37  	m |= uint32(val) << 5      // imm16
    38  	m |= uint32(shift&3) << 21 // hw
    39  	m |= _0b100101 << 23       // const
    40  	m |= uint32(opc&0x3) << 29 // opc
    41  	m |= _0b1 << 31            // sf
    42  
    43  	res := make([]byte, 4)
    44  	*(*uint32)(unsafe.Pointer(&res[0])) = m
    45  
    46  	return res
    47  }
    48  
    49  // jmpToOriginFunctionValue Assembles a jump to a function value
    50  func jmpToOriginFunctionValue(_, _ uintptr) (value []byte) {
    51  	panic("not support yet")
    52  }
    53  
    54  // checkAlreadyPatch 检测是否已经patch
    55  func checkAlreadyPatch(origin []byte) bool {
    56  	for i := 0; i < len(nopOpcode); i++ {
    57  		if origin[i] != nopOpcode[i] {
    58  			return false
    59  		}
    60  	}
    61  	return true
    62  }