github.com/tencent/goom@v1.0.1/internal/bytecode/addr.go (about)

     1  // Package bytecode 是内存字节码层面操作的工具集
     2  package bytecode
     3  
     4  import (
     5  	"encoding/hex"
     6  	"fmt"
     7  	"math"
     8  	"strings"
     9  
    10  	"github.com/tencent/goom/internal/arch/x86asm"
    11  )
    12  
    13  // opExpand 短地址指令 -> 长地址指令
    14  // 原始函数内部的短地址跳转无法满足长距离跳转时候,需要修改为长地址跳转, 因此同时需要将操作符指令修改为对应的长地址操作符指令
    15  var opExpand = map[uint32][]byte{
    16  	0x74: {0x0F, 0x84}, // JE: 74->0F
    17  	0x76: {0x0F, 0x86}, // JBE: 76->0F
    18  	0x7F: {0x0F, 0x8F},
    19  	0xEB: {0xE9}, // JMP: EB->E9 (Jump near, relative, displacement relative to next instruction.)
    20  }
    21  
    22  // DecodeRelativeAddr decode relative address, if jump to the front of current pos, return negative values
    23  func DecodeRelativeAddr(ins *x86asm.Inst, block []byte, offset int) int {
    24  	var isAdd = true
    25  	for i := 0; i < len(ins.Args); i++ {
    26  		arg := ins.Args[i]
    27  		if arg == nil {
    28  			break
    29  		}
    30  		addrArgs := arg.String()
    31  		if strings.HasPrefix(addrArgs, ".-") || strings.Contains(addrArgs, "RIP-") {
    32  			isAdd = false
    33  		}
    34  	}
    35  
    36  	relativeAddr := DecodeAddress(block[offset:offset+ins.PCRel], ins.PCRel)
    37  	if !isAdd && relativeAddr > 0 {
    38  		relativeAddr = -relativeAddr
    39  	}
    40  	return relativeAddr
    41  }
    42  
    43  // EncodeAddress 写入地址参数到函数字节码
    44  // len 地址值的位数
    45  // val 地址值
    46  // add 偏移量, 可为负数
    47  func EncodeAddress(ops []byte, addr []byte, addrLen int, val int, add int) []byte {
    48  	switch addrLen {
    49  	case 1:
    50  		if !isByteOverflow((int32)(int8(val)) + (int32)(add)) {
    51  			addr[0] = byte((int)(int8(val)) + add)
    52  			return toInst(ops, addr)
    53  		}
    54  		if opsNew, ok := opExpand[uint32(ops[0])]; ok {
    55  			addr = make([]byte, 4)
    56  			LittleEndian.PutInt32(addr, (int32)(int8(val))+int32(add)-
    57  				int32(len(addr)-addrLen)-int32(len(opsNew)-len(ops))) // 新增了4个字节,需要减去
    58  			ops = opsNew
    59  			return toInst(ops, addr)
    60  		}
    61  		panic("address overflow:" + hex.EncodeToString(ops) + ", addr:" + hex.EncodeToString(addr[:addrLen]))
    62  	case 2:
    63  		if !isInt16Overflow((int32)(int8(val)) + (int32)(add)) {
    64  			LittleEndian.PutInt16(addr, int16(val)+int16(add))
    65  			return toInst(ops, addr)
    66  		}
    67  		if opsNew, ok := opExpand[uint32(ops[0])<<16+uint32(ops[1])]; ok {
    68  			addr = make([]byte, 4)
    69  			LittleEndian.PutInt32(addr, (int32)(int8(val))+int32(add)-
    70  				int32(len(addr)-addrLen)-int32(len(opsNew)-len(ops))) // 新增了4个字节,需要减去
    71  			ops = opsNew
    72  			return toInst(ops, addr)
    73  		}
    74  		panic("address overflow:" + hex.EncodeToString(ops) + ", addr:" + hex.EncodeToString(addr[:addrLen]))
    75  	case 4:
    76  		LittleEndian.PutInt32(addr, int32(val)+int32(add))
    77  		return toInst(ops, addr)
    78  	case 8:
    79  		LittleEndian.PutInt64(addr, int64(val)+int64(add))
    80  		return toInst(ops, addr)
    81  	default:
    82  		panic(fmt.Sprintf("address overflow check error: add len not support:%d", addrLen))
    83  	}
    84  }
    85  
    86  func toInst(ops []byte, addr []byte) []byte {
    87  	result := make([]byte, 0)
    88  	result = append(result, ops...)
    89  	return append(result, addr...)
    90  }
    91  
    92  // DecodeAddress 从函数字节码中解析地址数值
    93  // len 地址值的位数
    94  func DecodeAddress(bytes []byte, len int) int {
    95  	switch len {
    96  	case 1:
    97  		return int(int8(bytes[0]))
    98  	case 2:
    99  		return int(LittleEndian.Int16(bytes))
   100  	case 4:
   101  		return int(LittleEndian.Int32(bytes))
   102  	case 8:
   103  		return int(LittleEndian.Int64(bytes))
   104  	default:
   105  		panic(fmt.Sprintf("decode address error: add len not support:%d", len))
   106  	}
   107  }
   108  
   109  // isByteOverflow 字节是否溢出
   110  func isByteOverflow(v int32) bool {
   111  	if v > 0 {
   112  		if v > math.MaxInt8 {
   113  			return true
   114  		}
   115  	} else {
   116  		if v < math.MinInt8 {
   117  			return true
   118  		}
   119  	}
   120  	return false
   121  }
   122  
   123  // isInt16Overflow  init16是否溢出
   124  func isInt16Overflow(v int32) bool {
   125  	if v > 0 {
   126  		if v > math.MaxInt16 {
   127  			return true
   128  		}
   129  	} else {
   130  		if v < math.MinInt16 {
   131  			return true
   132  		}
   133  	}
   134  	return false
   135  }
   136  
   137  // nolint
   138  func isInt32Overflow(v int64) bool {
   139  	if v > 0 {
   140  		if v > math.MaxInt32 {
   141  			return true
   142  		}
   143  	} else {
   144  		if v < math.MinInt32 {
   145  			return true
   146  		}
   147  	}
   148  	return false
   149  }