-
Notifications
You must be signed in to change notification settings - Fork 43
/
ppc_decomposer.go
132 lines (110 loc) · 2.75 KB
/
ppc_decomposer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
Gapstone is a Go binding for the Capstone disassembly library. For examples,
try reading the *_test.go files.
Library Author: Nguyen Anh Quynh
Binding Author: Ben Nagy
License: BSD style - see LICENSE file for details
(c) 2013 COSEINC. All Rights Reserved.
*/
package gapstone
// #cgo LDFLAGS: -lcapstone
// #cgo freebsd CFLAGS: -I/usr/local/include
// #cgo freebsd LDFLAGS: -L/usr/local/lib
// #include <stdlib.h>
// #include <capstone/capstone.h>
import "C"
import (
"reflect"
"unsafe"
)
// Accessed via insn.PPC.XXX
type PPCInstruction struct {
BC int
BH int
UpdateCR0 bool
Operands []PPCOperand
}
// Number of Operands of a given PPC_OP_* type
func (insn PPCInstruction) OpCount(optype uint) int {
count := 0
for _, op := range insn.Operands {
if op.Type == optype {
count++
}
}
return count
}
type PPCOperand struct {
Type uint // PPC_OP_* - determines which field is set below
Reg uint
Imm int64
Mem PPCMemoryOperand
CRX PPCCRXOperand
}
type PPCMemoryOperand struct {
Base uint
Disp int
}
type PPCCRXOperand struct {
Scale uint
Reg uint
Cond uint
}
func fillPPCHeader(raw C.cs_insn, insn *Instruction) {
if raw.detail == nil {
return
}
// Cast the cs_detail union
cs_ppc := (*C.cs_ppc)(unsafe.Pointer(&raw.detail.anon0[0]))
ppc := PPCInstruction{
BC: int(cs_ppc.bc),
BH: int(cs_ppc.bh),
UpdateCR0: bool(cs_ppc.update_cr0),
}
// Cast the op_info to a []C.cs_ppc_op
var ops []C.cs_ppc_op
oih := (*reflect.SliceHeader)(unsafe.Pointer(&ops))
oih.Data = uintptr(unsafe.Pointer(&cs_ppc.operands[0]))
oih.Len = int(cs_ppc.op_count)
oih.Cap = int(cs_ppc.op_count)
// Create the Go object for each operand
for _, cop := range ops {
if cop._type == PPC_OP_INVALID {
break
}
gop := new(PPCOperand)
gop.Type = uint(cop._type)
switch cop._type {
// fake a union by setting only the correct struct member
case PPC_OP_IMM:
gop.Imm = int64(*(*C.int32_t)(unsafe.Pointer(&cop.anon0[0])))
case PPC_OP_REG:
gop.Reg = uint(*(*C.uint)(unsafe.Pointer(&cop.anon0[0])))
case PPC_OP_MEM:
cmop := (*C.ppc_op_mem)(unsafe.Pointer(&cop.anon0[0]))
gop.Mem = PPCMemoryOperand{
Base: uint(cmop.base),
Disp: int(cmop.disp),
}
case PPC_OP_CRX:
ccrxop := (*C.ppc_op_crx)(unsafe.Pointer(&cop.anon0[0]))
gop.CRX = PPCCRXOperand{
Scale: uint(ccrxop.scale),
Reg: uint(ccrxop.reg),
Cond: uint(ccrxop.cond),
}
}
ppc.Operands = append(ppc.Operands, *gop)
}
insn.PPC = &ppc
}
func decomposePPC(e *Engine, raws []C.cs_insn) []Instruction {
decomposed := []Instruction{}
for _, raw := range raws {
decomp := new(Instruction)
fillGenericHeader(e, raw, decomp)
fillPPCHeader(raw, decomp)
decomposed = append(decomposed, *decomp)
}
return decomposed
}