github.com/Rookout/GoSDK@v0.1.48/pkg/services/disassembler/disassembler_amd64.go (about) 1 package disassembler 2 3 import ( 4 "fmt" 5 6 "github.com/Rookout/GoSDK/pkg/rookoutErrors" 7 "github.com/Rookout/GoSDK/pkg/utils" 8 "golang.org/x/arch/x86/x86asm" 9 ) 10 11 var maxInstLen = 15 12 13 type inst = x86asm.Inst 14 15 func (i *Instruction) GetDestPC() (uintptr, rookoutErrors.RookoutError) { 16 if !IsDirectCall(i) && !IsDirectJump(i) { 17 return 0, rookoutErrors.NewUnexpectedInstructionOp(i) 18 } 19 20 relDest := i.Args[0].(x86asm.Rel) 21 return uintptr(int64(relDest) + int64(i.PC) + int64(i.Len)), nil 22 } 23 24 25 func isArgRel(i *Instruction) bool { 26 _, ok := i.Args[0].(x86asm.Rel) 27 return ok 28 } 29 30 func IsDirectCall(i *Instruction) bool { 31 if i.Op != x86asm.CALL { 32 return false 33 } 34 return isArgRel(i) 35 } 36 37 func IsDirectJump(i *Instruction) bool { 38 switch i.Op { 39 case x86asm.JA, 40 x86asm.JAE, 41 x86asm.JB, 42 x86asm.JBE, 43 x86asm.JCXZ, 44 x86asm.JE, 45 x86asm.JECXZ, 46 x86asm.JG, 47 x86asm.JGE, 48 x86asm.JL, 49 x86asm.JLE, 50 x86asm.JMP, 51 x86asm.JNE, 52 x86asm.JNO, 53 x86asm.JNP, 54 x86asm.JNS, 55 x86asm.JO, 56 x86asm.JP, 57 x86asm.JRCXZ, 58 x86asm.JS: 59 return isArgRel(i) 60 } 61 return false 62 } 63 64 func decodeOne(bytes []byte) (*Instruction, rookoutErrors.RookoutError) { 65 inst, err := x86asm.Decode(bytes, 64) 66 if err != nil { 67 return nil, rookoutErrors.NewFailedToDecode(bytes, err) 68 } 69 70 return &Instruction{ 71 inst: inst, 72 Len: inst.Len, 73 }, nil 74 } 75 76 77 func DecodeOne(startPC uintptr) (*Instruction, rookoutErrors.RookoutError) { 78 funcAsm := utils.MakeSliceFromPointer(startPC, maxInstLen) 79 inst, err := decodeOne(funcAsm) 80 if err != nil { 81 return nil, rookoutErrors.NewFailedToDecode(funcAsm, err) 82 } 83 84 inst.PC = startPC 85 return inst, nil 86 } 87 88 89 func Decode(startPC uintptr, endPC uintptr, _ bool) ([]*Instruction, rookoutErrors.RookoutError) { 90 var instructions []*Instruction 91 funcLen := endPC - startPC 92 funcAsm := utils.MakeSliceFromPointer(startPC, int(funcLen)) 93 offset := uintptr(0) 94 95 for offset < funcLen { 96 inst, err := decodeOne(funcAsm[offset:]) 97 if err != nil { 98 err.AddArgument("funcAsm", fmt.Sprintf("%x", funcAsm)) 99 err.AddArgument("offset", offset) 100 err.AddArgument("startPC", startPC) 101 return nil, err 102 } 103 104 inst.PC = startPC + uintptr(offset) 105 inst.Offset = offset 106 107 instructions = append(instructions, inst) 108 offset += uintptr(inst.Len) 109 } 110 111 return instructions, nil 112 }