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  }