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 }