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

     1  package patch
     2  
     3  import "unsafe"
     4  
     5  // nopOpcode 空指令插入到原函数开头第一个字节, 用于判断原函数是否已经被 Patch 过
     6  const nopOpcode byte = 0x90
     7  
     8  // jmpToFunctionValue Assembles a jump to a function value
     9  func jmpToFunctionValue(_, to uintptr) (value []byte) {
    10  	return []byte{
    11  		0x90, // NOP
    12  		0x48, 0xBA,
    13  		byte(to),
    14  		byte(to >> 8),
    15  		byte(to >> 16),
    16  		byte(to >> 24),
    17  		byte(to >> 32),
    18  		byte(to >> 40),
    19  		byte(to >> 48),
    20  		byte(to >> 56), // movabs rdx,to
    21  		0xFF, 0x22,     // jmp QWORD PTR [rdx]
    22  	}
    23  }
    24  
    25  // jmpToOriginFunctionValue Assembles a jump to a function value
    26  func jmpToOriginFunctionValue(from, to uintptr) (value []byte) {
    27  	if relative(from, to) {
    28  		var dis uint32
    29  		if to > from {
    30  			dis = uint32(int32(to-from) - 5)
    31  		} else {
    32  			dis = uint32(-int32(from-to) - 5)
    33  		}
    34  
    35  		return []byte{
    36  			0xe9,
    37  			byte(dis),
    38  			byte(dis >> 8),
    39  			byte(dis >> 16),
    40  			byte(dis >> 24),
    41  		}
    42  	}
    43  
    44  	return []byte{
    45  		0x48, 0xBA,
    46  		byte(to),
    47  		byte(to >> 8),
    48  		byte(to >> 16),
    49  		byte(to >> 24),
    50  		byte(to >> 32),
    51  		byte(to >> 40),
    52  		byte(to >> 48),
    53  		byte(to >> 56), // movabs rdx,to
    54  		0xFF, 0x22,     // jmp QWORD PTR [rdx]
    55  	}
    56  }
    57  
    58  // relative 判断两个指针间隔是否可以用相对地址表示
    59  func relative(from uintptr, to uintptr) bool {
    60  	delta := int64(from - to)
    61  	if unsafe.Sizeof(uintptr(0)) == unsafe.Sizeof(int32(0)) {
    62  		delta = int64(int32(from - to))
    63  	}
    64  
    65  	// 跨度大于2G 时
    66  	relative := delta <= 0x7fffffff
    67  
    68  	if delta < 0 {
    69  		delta = -delta
    70  		relative = delta <= 0x80000000
    71  	}
    72  	return relative
    73  }
    74  
    75  // checkAlreadyPatch 检测是否已经 patch
    76  func checkAlreadyPatch(origin []byte) bool {
    77  	return origin[0] == nopOpcode
    78  }