1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#ifdef __KERNEL__
22#include <linux/string.h>
23#else
24#include <string.h>
25#endif
26#include "../include/asm/inat.h"
27#include "../include/asm/insn.h"
28
29#include "../include/asm/emulate_prefix.h"
30
31
32#define validate_next(t, insn, n) \
33 ((insn)->next_byte + sizeof(t) + n <= (insn)->end_kaddr)
34
35#define __get_next(t, insn) \
36 ({ t r = *(t*)insn->next_byte; insn->next_byte += sizeof(t); r; })
37
38#define __peek_nbyte_next(t, insn, n) \
39 ({ t r = *(t*)((insn)->next_byte + n); r; })
40
41#define get_next(t, insn) \
42 ({ if (unlikely(!validate_next(t, insn, 0))) goto err_out; __get_next(t, insn); })
43
44#define peek_nbyte_next(t, insn, n) \
45 ({ if (unlikely(!validate_next(t, insn, n))) goto err_out; __peek_nbyte_next(t, insn, n); })
46
47#define peek_next(t, insn) peek_nbyte_next(t, insn, 0)
48
49
50
51
52
53
54
55void insn_init(struct insn *insn, const void *kaddr, int buf_len, int x86_64)
56{
57
58
59
60
61 if (buf_len > MAX_INSN_SIZE)
62 buf_len = MAX_INSN_SIZE;
63
64 memset(insn, 0, sizeof(*insn));
65 insn->kaddr = kaddr;
66 insn->end_kaddr = kaddr + buf_len;
67 insn->next_byte = kaddr;
68 insn->x86_64 = x86_64 ? 1 : 0;
69 insn->opnd_bytes = 4;
70 if (x86_64)
71 insn->addr_bytes = 8;
72 else
73 insn->addr_bytes = 4;
74}
75
76static const insn_byte_t xen_prefix[] = { __XEN_EMULATE_PREFIX };
77static const insn_byte_t kvm_prefix[] = { __KVM_EMULATE_PREFIX };
78
79static int __insn_get_emulate_prefix(struct insn *insn,
80 const insn_byte_t *prefix, size_t len)
81{
82 size_t i;
83
84 for (i = 0; i < len; i++) {
85 if (peek_nbyte_next(insn_byte_t, insn, i) != prefix[i])
86 goto err_out;
87 }
88
89 insn->emulate_prefix_size = len;
90 insn->next_byte += len;
91
92 return 1;
93
94err_out:
95 return 0;
96}
97
98static void insn_get_emulate_prefix(struct insn *insn)
99{
100 if (__insn_get_emulate_prefix(insn, xen_prefix, sizeof(xen_prefix)))
101 return;
102
103 __insn_get_emulate_prefix(insn, kvm_prefix, sizeof(kvm_prefix));
104}
105
106
107
108
109
110
111
112
113
114void insn_get_prefixes(struct insn *insn)
115{
116 struct insn_field *prefixes = &insn->prefixes;
117 insn_attr_t attr;
118 insn_byte_t b, lb;
119 int i, nb;
120
121 if (prefixes->got)
122 return;
123
124 insn_get_emulate_prefix(insn);
125
126 nb = 0;
127 lb = 0;
128 b = peek_next(insn_byte_t, insn);
129 attr = inat_get_opcode_attribute(b);
130 while (inat_is_legacy_prefix(attr)) {
131
132 for (i = 0; i < nb; i++)
133 if (prefixes->bytes[i] == b)
134 goto found;
135 if (nb == 4)
136
137 break;
138 prefixes->bytes[nb++] = b;
139 if (inat_is_address_size_prefix(attr)) {
140
141 if (insn->x86_64)
142 insn->addr_bytes ^= 12;
143 else
144 insn->addr_bytes ^= 6;
145 } else if (inat_is_operand_size_prefix(attr)) {
146
147 insn->opnd_bytes ^= 6;
148 }
149found:
150 prefixes->nbytes++;
151 insn->next_byte++;
152 lb = b;
153 b = peek_next(insn_byte_t, insn);
154 attr = inat_get_opcode_attribute(b);
155 }
156
157 if (lb && lb != insn->prefixes.bytes[3]) {
158 if (unlikely(insn->prefixes.bytes[3])) {
159
160 b = insn->prefixes.bytes[3];
161 for (i = 0; i < nb; i++)
162 if (prefixes->bytes[i] == lb)
163 prefixes->bytes[i] = b;
164 }
165 insn->prefixes.bytes[3] = lb;
166 }
167
168
169 if (insn->x86_64) {
170 b = peek_next(insn_byte_t, insn);
171 attr = inat_get_opcode_attribute(b);
172 if (inat_is_rex_prefix(attr)) {
173 insn->rex_prefix.value = b;
174 insn->rex_prefix.nbytes = 1;
175 insn->next_byte++;
176 if (X86_REX_W(b))
177
178 insn->opnd_bytes = 8;
179 }
180 }
181 insn->rex_prefix.got = 1;
182
183
184 b = peek_next(insn_byte_t, insn);
185 attr = inat_get_opcode_attribute(b);
186 if (inat_is_vex_prefix(attr)) {
187 insn_byte_t b2 = peek_nbyte_next(insn_byte_t, insn, 1);
188 if (!insn->x86_64) {
189
190
191
192
193
194 if (X86_MODRM_MOD(b2) != 3)
195 goto vex_end;
196 }
197 insn->vex_prefix.bytes[0] = b;
198 insn->vex_prefix.bytes[1] = b2;
199 if (inat_is_evex_prefix(attr)) {
200 b2 = peek_nbyte_next(insn_byte_t, insn, 2);
201 insn->vex_prefix.bytes[2] = b2;
202 b2 = peek_nbyte_next(insn_byte_t, insn, 3);
203 insn->vex_prefix.bytes[3] = b2;
204 insn->vex_prefix.nbytes = 4;
205 insn->next_byte += 4;
206 if (insn->x86_64 && X86_VEX_W(b2))
207
208 insn->opnd_bytes = 8;
209 } else if (inat_is_vex3_prefix(attr)) {
210 b2 = peek_nbyte_next(insn_byte_t, insn, 2);
211 insn->vex_prefix.bytes[2] = b2;
212 insn->vex_prefix.nbytes = 3;
213 insn->next_byte += 3;
214 if (insn->x86_64 && X86_VEX_W(b2))
215
216 insn->opnd_bytes = 8;
217 } else {
218
219
220
221
222
223 insn->vex_prefix.bytes[2] = b2 & 0x7f;
224 insn->vex_prefix.nbytes = 2;
225 insn->next_byte += 2;
226 }
227 }
228vex_end:
229 insn->vex_prefix.got = 1;
230
231 prefixes->got = 1;
232
233err_out:
234 return;
235}
236
237
238
239
240
241
242
243
244
245
246
247void insn_get_opcode(struct insn *insn)
248{
249 struct insn_field *opcode = &insn->opcode;
250 insn_byte_t op;
251 int pfx_id;
252 if (opcode->got)
253 return;
254 if (!insn->prefixes.got)
255 insn_get_prefixes(insn);
256
257
258 op = get_next(insn_byte_t, insn);
259 opcode->bytes[0] = op;
260 opcode->nbytes = 1;
261
262
263 if (insn_is_avx(insn)) {
264 insn_byte_t m, p;
265 m = insn_vex_m_bits(insn);
266 p = insn_vex_p_bits(insn);
267 insn->attr = inat_get_avx_attribute(op, m, p);
268 if ((inat_must_evex(insn->attr) && !insn_is_evex(insn)) ||
269 (!inat_accept_vex(insn->attr) &&
270 !inat_is_group(insn->attr)))
271 insn->attr = 0;
272 goto end;
273 }
274
275 insn->attr = inat_get_opcode_attribute(op);
276 while (inat_is_escape(insn->attr)) {
277
278 op = get_next(insn_byte_t, insn);
279 opcode->bytes[opcode->nbytes++] = op;
280 pfx_id = insn_last_prefix_id(insn);
281 insn->attr = inat_get_escape_attribute(op, pfx_id, insn->attr);
282 }
283 if (inat_must_vex(insn->attr))
284 insn->attr = 0;
285end:
286 opcode->got = 1;
287
288err_out:
289 return;
290}
291
292
293
294
295
296
297
298
299
300void insn_get_modrm(struct insn *insn)
301{
302 struct insn_field *modrm = &insn->modrm;
303 insn_byte_t pfx_id, mod;
304 if (modrm->got)
305 return;
306 if (!insn->opcode.got)
307 insn_get_opcode(insn);
308
309 if (inat_has_modrm(insn->attr)) {
310 mod = get_next(insn_byte_t, insn);
311 modrm->value = mod;
312 modrm->nbytes = 1;
313 if (inat_is_group(insn->attr)) {
314 pfx_id = insn_last_prefix_id(insn);
315 insn->attr = inat_get_group_attribute(mod, pfx_id,
316 insn->attr);
317 if (insn_is_avx(insn) && !inat_accept_vex(insn->attr))
318 insn->attr = 0;
319 }
320 }
321
322 if (insn->x86_64 && inat_is_force64(insn->attr))
323 insn->opnd_bytes = 8;
324 modrm->got = 1;
325
326err_out:
327 return;
328}
329
330
331
332
333
334
335
336
337
338int insn_rip_relative(struct insn *insn)
339{
340 struct insn_field *modrm = &insn->modrm;
341
342 if (!insn->x86_64)
343 return 0;
344 if (!modrm->got)
345 insn_get_modrm(insn);
346
347
348
349
350 return (modrm->nbytes && (modrm->value & 0xc7) == 0x5);
351}
352
353
354
355
356
357
358
359
360void insn_get_sib(struct insn *insn)
361{
362 insn_byte_t modrm;
363
364 if (insn->sib.got)
365 return;
366 if (!insn->modrm.got)
367 insn_get_modrm(insn);
368 if (insn->modrm.nbytes) {
369 modrm = (insn_byte_t)insn->modrm.value;
370 if (insn->addr_bytes != 2 &&
371 X86_MODRM_MOD(modrm) != 3 && X86_MODRM_RM(modrm) == 4) {
372 insn->sib.value = get_next(insn_byte_t, insn);
373 insn->sib.nbytes = 1;
374 }
375 }
376 insn->sib.got = 1;
377
378err_out:
379 return;
380}
381
382
383
384
385
386
387
388
389
390
391void insn_get_displacement(struct insn *insn)
392{
393 insn_byte_t mod, rm, base;
394
395 if (insn->displacement.got)
396 return;
397 if (!insn->sib.got)
398 insn_get_sib(insn);
399 if (insn->modrm.nbytes) {
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417 mod = X86_MODRM_MOD(insn->modrm.value);
418 rm = X86_MODRM_RM(insn->modrm.value);
419 base = X86_SIB_BASE(insn->sib.value);
420 if (mod == 3)
421 goto out;
422 if (mod == 1) {
423 insn->displacement.value = get_next(signed char, insn);
424 insn->displacement.nbytes = 1;
425 } else if (insn->addr_bytes == 2) {
426 if ((mod == 0 && rm == 6) || mod == 2) {
427 insn->displacement.value =
428 get_next(short, insn);
429 insn->displacement.nbytes = 2;
430 }
431 } else {
432 if ((mod == 0 && rm == 5) || mod == 2 ||
433 (mod == 0 && base == 5)) {
434 insn->displacement.value = get_next(int, insn);
435 insn->displacement.nbytes = 4;
436 }
437 }
438 }
439out:
440 insn->displacement.got = 1;
441
442err_out:
443 return;
444}
445
446
447static int __get_moffset(struct insn *insn)
448{
449 switch (insn->addr_bytes) {
450 case 2:
451 insn->moffset1.value = get_next(short, insn);
452 insn->moffset1.nbytes = 2;
453 break;
454 case 4:
455 insn->moffset1.value = get_next(int, insn);
456 insn->moffset1.nbytes = 4;
457 break;
458 case 8:
459 insn->moffset1.value = get_next(int, insn);
460 insn->moffset1.nbytes = 4;
461 insn->moffset2.value = get_next(int, insn);
462 insn->moffset2.nbytes = 4;
463 break;
464 default:
465 goto err_out;
466 }
467 insn->moffset1.got = insn->moffset2.got = 1;
468
469 return 1;
470
471err_out:
472 return 0;
473}
474
475
476static int __get_immv32(struct insn *insn)
477{
478 switch (insn->opnd_bytes) {
479 case 2:
480 insn->immediate.value = get_next(short, insn);
481 insn->immediate.nbytes = 2;
482 break;
483 case 4:
484 case 8:
485 insn->immediate.value = get_next(int, insn);
486 insn->immediate.nbytes = 4;
487 break;
488 default:
489 goto err_out;
490 }
491
492 return 1;
493
494err_out:
495 return 0;
496}
497
498
499static int __get_immv(struct insn *insn)
500{
501 switch (insn->opnd_bytes) {
502 case 2:
503 insn->immediate1.value = get_next(short, insn);
504 insn->immediate1.nbytes = 2;
505 break;
506 case 4:
507 insn->immediate1.value = get_next(int, insn);
508 insn->immediate1.nbytes = 4;
509 break;
510 case 8:
511 insn->immediate1.value = get_next(int, insn);
512 insn->immediate1.nbytes = 4;
513 insn->immediate2.value = get_next(int, insn);
514 insn->immediate2.nbytes = 4;
515 break;
516 default:
517 goto err_out;
518 }
519 insn->immediate1.got = insn->immediate2.got = 1;
520
521 return 1;
522err_out:
523 return 0;
524}
525
526
527static int __get_immptr(struct insn *insn)
528{
529 switch (insn->opnd_bytes) {
530 case 2:
531 insn->immediate1.value = get_next(short, insn);
532 insn->immediate1.nbytes = 2;
533 break;
534 case 4:
535 insn->immediate1.value = get_next(int, insn);
536 insn->immediate1.nbytes = 4;
537 break;
538 case 8:
539
540 return 0;
541 default:
542 goto err_out;
543 }
544 insn->immediate2.value = get_next(unsigned short, insn);
545 insn->immediate2.nbytes = 2;
546 insn->immediate1.got = insn->immediate2.got = 1;
547
548 return 1;
549err_out:
550 return 0;
551}
552
553
554
555
556
557
558
559
560
561
562void insn_get_immediate(struct insn *insn)
563{
564 if (insn->immediate.got)
565 return;
566 if (!insn->displacement.got)
567 insn_get_displacement(insn);
568
569 if (inat_has_moffset(insn->attr)) {
570 if (!__get_moffset(insn))
571 goto err_out;
572 goto done;
573 }
574
575 if (!inat_has_immediate(insn->attr))
576
577 goto done;
578
579 switch (inat_immediate_size(insn->attr)) {
580 case INAT_IMM_BYTE:
581 insn->immediate.value = get_next(signed char, insn);
582 insn->immediate.nbytes = 1;
583 break;
584 case INAT_IMM_WORD:
585 insn->immediate.value = get_next(short, insn);
586 insn->immediate.nbytes = 2;
587 break;
588 case INAT_IMM_DWORD:
589 insn->immediate.value = get_next(int, insn);
590 insn->immediate.nbytes = 4;
591 break;
592 case INAT_IMM_QWORD:
593 insn->immediate1.value = get_next(int, insn);
594 insn->immediate1.nbytes = 4;
595 insn->immediate2.value = get_next(int, insn);
596 insn->immediate2.nbytes = 4;
597 break;
598 case INAT_IMM_PTR:
599 if (!__get_immptr(insn))
600 goto err_out;
601 break;
602 case INAT_IMM_VWORD32:
603 if (!__get_immv32(insn))
604 goto err_out;
605 break;
606 case INAT_IMM_VWORD:
607 if (!__get_immv(insn))
608 goto err_out;
609 break;
610 default:
611
612 goto err_out;
613 }
614 if (inat_has_second_immediate(insn->attr)) {
615 insn->immediate2.value = get_next(signed char, insn);
616 insn->immediate2.nbytes = 1;
617 }
618done:
619 insn->immediate.got = 1;
620
621err_out:
622 return;
623}
624
625
626
627
628
629
630
631
632void insn_get_length(struct insn *insn)
633{
634 if (insn->length)
635 return;
636 if (!insn->immediate.got)
637 insn_get_immediate(insn);
638 insn->length = (unsigned char)((unsigned long)insn->next_byte
639 - (unsigned long)insn->kaddr);
640}
641