mask repeat prefix out of insn prefix
[fkvm-libfkvm.git] / disasm.c
blob75d89e12d70cce9024d4dfa7349fc16f38c7929d
1 #define FKVM_INTERNAL
2 #include <sys/fkvm.h>
4 #include <unistd.h>
5 #include <stdlib.h>
6 #include <stdbool.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <errno.h>
10 #include <inttypes.h>
11 #include <assert.h>
12 #include <libdis.h>
14 #include "disasm.h"
15 #include "libkvm.h"
16 #include "libfkvm-common.h"
18 int
19 kvm_reg_from_x86_reg(int x86_reg_id)
21 static const int const map[] = {
22 -1,
23 KVM_REG_RAX,
24 KVM_REG_RCX,
25 KVM_REG_RDX,
26 KVM_REG_RBX,
27 KVM_REG_RSP,
28 KVM_REG_RBP,
29 KVM_REG_RSI,
30 KVM_REG_RDI,
31 KVM_REG_RAX,
32 KVM_REG_RCX,
33 KVM_REG_RDX,
34 KVM_REG_RBX,
35 KVM_REG_RSP,
36 KVM_REG_RBP,
37 KVM_REG_RSI,
38 KVM_REG_RDI,
39 KVM_REG_RAX,
40 KVM_REG_RCX,
41 KVM_REG_RDX,
42 KVM_REG_RBX,
43 KVM_REG_RAX,
44 KVM_REG_RCX,
45 KVM_REG_RDX,
46 KVM_REG_RBX,
47 -1, /* mm0 */
48 -1, /* mm1 */
49 -1, /* mm2 */
50 -1, /* mm3 */
51 -1, /* mm4 */
52 -1, /* mm5 */
53 -1, /* mm6 */
54 -1, /* mm7 */
55 -1, /* xmm0 */
56 -1, /* xmm1 */
57 -1, /* xmm2 */
58 -1, /* xmm3 */
59 -1, /* xmm4 */
60 -1, /* xmm5 */
61 -1, /* xmm6 */
62 -1, /* xmm7 */
63 -1, /* dr0 */
64 -1, /* dr1 */
65 -1, /* dr2 */
66 -1, /* dr3 */
67 -1, /* dr4 */
68 -1, /* dr5 */
69 -1, /* dr6 */
70 -1, /* dr7 */
71 -1, /* cr0 */
72 -1, /* cr1 */
73 -1, /* cr2 */
74 -1, /* cr3 */
75 -1, /* cr4 */
76 -1, /* cr5 */
77 -1, /* cr6 */
78 -1, /* cr7 */
79 -1, /* tr0 */
80 -1, /* tr1 */
81 -1, /* tr2 */
82 -1, /* tr3 */
83 -1, /* tr4 */
84 -1, /* tr5 */
85 -1, /* tr6 */
86 -1, /* tr7 */
87 -1, /* es */
88 -1, /* cs */
89 -1, /* ss */
90 -1, /* ds */
92 -1, /* fs */
93 -1, /* gs */
94 -1, /* ldtr */
95 -1, /* gdtr */
96 -1, /* st(0) */
97 -1, /* st(1) */
98 -1, /* st(2) */
99 -1, /* st(3) */
100 -1, /* st(4) */
101 -1, /* st(5) */
102 -1, /* st(6) */
103 -1, /* st(7) */
104 -1, /* eflags, */
105 -1, /* fpctrl, */
106 -1, /* fpstat */
107 -1, /* fptag, */
108 -1, /* eip */
109 -1, /* ip */
110 -1, /* idtr */
111 -1, /* mxcsr */
112 -1, /* tr */
113 -1, /* cs_msr */
114 -1, /* esp_msr */
115 -1, /* eip_msr */
118 if (x86_reg_id <= 0 || x86_reg_id >= ARRAY_SIZE(map))
119 return -1;
120 return map[x86_reg_id];
124 cr_num_from_x86_reg(int x86_reg_id)
126 /* CR0: 49
127 CR1: 50
128 CR2: 51
129 CR3: 52
130 CR4: 53
131 CR5: 54
132 CR6: 55
133 CR7: 58 */
134 int cr_num;
135 cr_num = x86_reg_id - 49;
136 if (cr_num >= 0 && cr_num <= 7)
137 return cr_num;
138 else
139 return -1;
142 struct kvm_segment*
143 kvm_seg_from_x86_op(struct kvm_sregs *sregs, x86_op_t *op)
145 switch (op->flags & 0xF00) {
146 case op_es_seg: return &sregs->es;
147 case op_cs_seg: return &sregs->cs;
148 case op_ss_seg: return &sregs->ss;
149 case op_ds_seg: return &sregs->ds;
150 case op_fs_seg: return &sregs->fs;
151 case op_gs_seg: return &sregs->gs;
152 default:
153 EXIT_ERR_PATH();
154 return NULL;
159 uint64_t
160 get_source_data(struct kvm_regs *regs, x86_op_t *op)
162 uint64_t source;
164 if (op->type == op_register) {
165 source = kvm_regs_get(regs,
166 kvm_reg_from_x86_reg(op->data.reg.id));
168 else if (op->type == op_immediate) {
169 source = op->data.qword;
171 else {
172 EXIT();
175 //printf("source = %" PRIx64 "\n", source);
177 source = mask_reg(source, x86_operand_size(op));
178 return source;
181 uint64_t
182 get_memi_address(struct kvm_regs *regs, struct kvm_sregs *sregs,
183 x86_op_t *op, size_t size)
185 struct kvm_segment *segment;
186 uint64_t address = 0;
188 if (op->type == op_expression) {
189 int reg_idx;
190 x86_ea_t *ea;
192 ea = &op->data.expression;
194 if (ea->base.id != 0) {
195 reg_idx = kvm_reg_from_x86_reg(ea->base.id);
196 address += kvm_regs_get(regs, reg_idx);
199 if (ea->index.id != 0) {
200 reg_idx = kvm_reg_from_x86_reg(ea->index.id);
201 address += ea->scale * kvm_regs_get(regs, reg_idx);
204 if (ea->disp_size != 0 && ea->disp != 0) {
205 address += ea->disp; /* TODO: disp_sign ? */
208 else if (op->type == op_offset) {
209 address = op->data.offset;
211 else {
212 EXIT(); //TODO
215 //printf("address = %" PRIx64 "\n", address);
216 address = mask_reg(address, size);
218 switch (op->flags & ~0xFF) {
219 case op_cs_seg:
220 segment = &sregs->cs;
221 break;
222 case op_ds_seg:
223 segment = &sregs->ds;
224 break;
225 case op_es_seg:
226 segment = &sregs->es;
227 break;
228 case op_fs_seg:
229 segment = &sregs->fs;
230 break;
231 case op_gs_seg:
232 segment = &sregs->gs;
233 break;
234 case op_ss_seg:
235 segment = &sregs->ss;
236 break;
237 default:
238 assert(0);
239 return -1;
242 /* if (reg_value > segment->limit) */
244 //printf("segment base: %" PRIx64 "\n", segment->base);
245 return segment->base + address;
248 unsigned int
249 get_x86_insn(const uint64_t insn_addr, x86_insn_t *insn)
251 uint8_t buf[MAX_INSN_SIZE];
252 unsigned int insn_size;
254 cpu_virtual_memory_rw(insn_addr, buf, MAX_INSN_SIZE, 0);
256 #if 1
258 int i;
259 printf("buf @ 0x%" PRIx64 ":", insn_addr);
260 for (i = 0; i < MAX_INSN_SIZE; i++)
261 printf(" %02x", buf[i]);
262 printf("\n");
265 #endif
267 insn_size = x86_disasm(buf, MAX_INSN_SIZE, 0, 0, insn);
268 if (insn_size == 0)
269 return -1;
271 #if 1
273 char line[80];
274 x86_format_insn(insn, line, 80, intel_syntax);
275 printf("%s\n", line);
277 #endif
279 return insn_size;
282 void
283 libdisasm_init(size_t reg_size)
285 if (reg_size == 2) {
286 x86_init(opt_16_bit, NULL, NULL);
288 else if (reg_size == 4) {
289 x86_init(opt_none, NULL, NULL);
291 else {
292 EXIT();
296 void
297 libdisasm_cleanup()
299 if (!x86_cleanup())
300 EXIT_ERR_PATH();