/[pearpc]/src/debug/x86dis.cc
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /src/debug/x86dis.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations)
Wed Sep 5 17:11:21 2007 UTC (16 years, 7 months ago) by dpavlin
File size: 24028 byte(s)
import upstream CVS
1 /*
2 * HT Editor
3 * x86dis.cc
4 *
5 * Copyright (C) 1999-2002 Stefan Weyergraf
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <cstdio>
22 #include <cstring>
23 #include <cstdlib>
24
25 #include "x86dis.h"
26
27 #define mkmod(modrm) (((modrm)>>6)&3)
28 #define mkreg(modrm) (((modrm)>>3)&7)
29 #define mkrm(modrm) ((modrm)&7)
30
31 #define mkscale(modrm) (((modrm)>>6)&3)
32 #define mkindex(modrm) (((modrm)>>3)&7)
33 #define mkbase(modrm) ((modrm)&7)
34
35 int modrm16_1[8] = { X86_REG_BX, X86_REG_BX, X86_REG_BP, X86_REG_BP,
36 X86_REG_SI, X86_REG_DI, X86_REG_BP, X86_REG_BX};
37 int modrm16_2[8] = { X86_REG_SI, X86_REG_DI, X86_REG_SI, X86_REG_DI,
38 X86_REG_NO, X86_REG_NO, X86_REG_NO, X86_REG_NO};
39
40 int sibbase[8] = { X86_REG_AX, X86_REG_CX, X86_REG_DX, X86_REG_BX,
41 X86_REG_SP, X86_REG_BP, X86_REG_SI, X86_REG_DI };
42
43 int sibindex[8] = { X86_REG_AX, X86_REG_CX, X86_REG_DX, X86_REG_BX,
44 X86_REG_NO, X86_REG_BP, X86_REG_SI, X86_REG_DI };
45
46 int sibscale[4] = {1, 2, 4, 8};
47
48 /*
49 * CLASS X86Disassembler
50 */
51
52 X86Disassembler::X86Disassembler()
53 {
54 }
55
56 X86Disassembler::X86Disassembler(int _opsize, int _addrsize)
57 {
58 opsize=_opsize;
59 addrsize=_addrsize;
60 }
61
62 X86Disassembler::~X86Disassembler()
63 {
64 }
65
66 dis_insn *X86Disassembler::decode(const byte *code, int Maxlen, CPU_ADDR Addr)
67 {
68 ocodep=code;
69 /* initialize */
70 codep=ocodep;
71 maxlen=Maxlen;
72 seg=Addr.addr32.seg;
73 addr=Addr.addr32.offset;
74 modrm=-1;
75 sib=-1;
76 memset(&insn, 0, sizeof(insn));
77 insn.invalid=false;
78 insn.eopsize=opsize;
79 insn.eaddrsize=opsize;
80
81 prefixes();
82
83 insn.opcode=c;
84 decode_insn(&x86_insns[insn.opcode]);
85
86 if (insn.invalid) {
87 insn.name="db";
88 insn.size=1;
89 insn.op[0].type=X86_OPTYPE_IMM;
90 insn.op[0].size=1;
91 insn.op[0].imm=*code;
92 insn.lockprefix=X86_PREFIX_NO;
93 insn.repprefix=X86_PREFIX_NO;
94 insn.segprefix=X86_PREFIX_NO;
95 for (int i=1; i<3; i++) insn.op[i].type=X86_OPTYPE_EMPTY;
96 } else {
97 insn.size=codep-ocodep;
98 }
99 return &insn;
100 }
101
102 void X86Disassembler::decode_modrm(x86_insn_op *op, char size, int allow_reg, int allow_mem, int mmx)
103 {
104 int modrm=getmodrm();
105 int mod=mkmod(modrm);
106 int rm=mkrm(modrm);
107 if (mod==3) {
108 /* reg */
109 if (!allow_reg) {
110 invalidate();
111 return;
112 }
113 if (mmx) {
114 op->type=X86_OPTYPE_MMX;
115 op->size=8;
116 op->mmx=rm;
117 } else {
118 op->type=X86_OPTYPE_REG;
119 op->size=esizeop(size);
120 op->reg=rm;
121 }
122 } else {
123 /* mem */
124 if (!allow_mem) {
125 invalidate();
126 return;
127 }
128 op->mem.addrsize=insn.eaddrsize;
129 if (insn.eaddrsize==X86_ADDRSIZE16) {
130 op->type=X86_OPTYPE_MEM;
131 op->size=esizeop(size);
132 op->mem.floatptr=isfloat(size);
133 if ((mod==0) && (rm==6)) {
134 op->mem.hasdisp=1;
135 op->mem.disp=getword();
136 op->mem.base=X86_REG_NO;
137 op->mem.index=X86_REG_NO;
138 op->mem.scale=0;
139 } else {
140 op->mem.base=modrm16_1[rm];
141 op->mem.index=modrm16_2[rm];
142 op->mem.scale=1;
143 switch (mod) {
144 case 0:
145 op->mem.hasdisp=0;
146 op->mem.disp=0;
147 break;
148 case 1:
149 op->mem.hasdisp=1;
150 op->mem.disp=(char)getbyte();
151 break;
152 case 2:
153 op->mem.hasdisp=1;
154 op->mem.disp=(short)getword();
155 break;
156 }
157 }
158 } else {
159 op->type=X86_OPTYPE_MEM;
160 op->size=esizeop(size);
161 op->mem.floatptr=isfloat(size);
162 if ((mod==0) && (rm==5)) {
163 op->mem.hasdisp=1;
164 op->mem.disp=getdword();
165 op->mem.base=X86_REG_NO;
166 op->mem.index=X86_REG_NO;
167 op->mem.scale=0;
168 } else if (rm==4) {
169 decode_sib(op, mod);
170 } else {
171 op->mem.base=rm;
172 op->mem.index=X86_REG_NO;
173 op->mem.scale=1;
174 switch (mod) {
175 case 0:
176 op->mem.hasdisp=0;
177 op->mem.disp=0;
178 break;
179 case 1:
180 op->mem.hasdisp=1;
181 op->mem.disp=(char)getbyte();
182 break;
183 case 2:
184 op->mem.hasdisp=1;
185 op->mem.disp=getdword();
186 break;
187 }
188 }
189 }
190 }
191 }
192
193 void X86Disassembler::decode_insn(x86opc_insn *xinsn)
194 {
195 if (!xinsn->name) {
196 x86opc_insn_op_special special=*((x86opc_insn_op_special*)(&xinsn->op[0]));
197 switch (special.type) {
198 case SPECIAL_TYPE_INVALID:
199 invalidate();
200 break;
201 case SPECIAL_TYPE_PREFIX:
202 switch (c) {
203 case 0x0f:
204 if (insn.opcodeclass == X86DIS_OPCODE_CLASS_STD) {
205 insn.opcode = getbyte();
206 insn.opcodeclass = X86DIS_OPCODE_CLASS_EXT;
207 decode_insn(&x86_insns_ext[insn.opcode]);
208 break;
209 }
210 default:
211 invalidate();
212 break;
213 }
214 break;
215 case SPECIAL_TYPE_GROUP: {
216 int m = mkreg(getmodrm());
217 insn.opcode |= m<<8;
218 decode_insn(&x86_group_insns[(int)special.data][m]);
219 break;
220 }
221 case SPECIAL_TYPE_FGROUP: {
222 int m = getmodrm();
223 if (mkmod(m) == 3) {
224 x86opc_finsn f = x86_float_group_insns[(int)special.data][mkreg(m)];
225 /* fprintf(stderr, "special.data=%d, m=%d, mkreg(m)=%d, mkrm(m)=%d\n", special.data, m, mkreg(m), mkrm(m));*/
226 if (f.group) {
227 decode_insn(&f.group[mkrm(m)]);
228 } else if (f.insn.name) {
229 decode_insn(&f.insn);
230 } else invalidate();
231 } else {
232 decode_insn(&x86_modfloat_group_insns[(int)special.data][mkreg(m)]);
233 }
234 break;
235 }
236 }
237 } else {
238 insn.name=xinsn->name;
239 for (int i=0; i<3; i++) {
240 decode_op(&insn.op[i], &xinsn->op[i]);
241 }
242 }
243 }
244
245 void X86Disassembler::decode_op(x86_insn_op *op, x86opc_insn_op *xop)
246 {
247 switch (xop->type) {
248 case TYPE_0:
249 return;
250 case TYPE_A: {
251 /* direct address without ModR/M */
252 op->type=X86_OPTYPE_FARPTR;
253 op->size=esizeop(xop->size);
254 switch (op->size) {
255 case 4:
256 op->farptr.offset=getword();
257 op->farptr.seg=getword();
258 break;
259 case 6:
260 op->farptr.offset=getdword();
261 op->farptr.seg=getword();
262 break;
263 }
264 break;
265 }
266 case TYPE_C: {
267 /* reg of ModR/M picks control register */
268 op->type=X86_OPTYPE_CRX;
269 op->size=esizeop(xop->size);
270 op->crx=mkreg(getmodrm());
271 break;
272 }
273 case TYPE_D: {
274 /* reg of ModR/M picks debug register */
275 op->type=X86_OPTYPE_DRX;
276 op->size=esizeop(xop->size);
277 op->drx=mkreg(getmodrm());
278 break;
279 }
280 case TYPE_E: {
281 /* ModR/M (general reg or memory) */
282 decode_modrm(op, xop->size, (xop->size!=SIZE_P), 1, 0);
283 break;
284 }
285 case TYPE_F: {
286 /* r/m of ModR/M picks a fpu register */
287 op->type=X86_OPTYPE_STX;
288 op->size=10;
289 op->stx=mkrm(getmodrm());
290 break;
291 }
292 case TYPE_Fx: {
293 /* extra picks a fpu register */
294 op->type=X86_OPTYPE_STX;
295 op->size=10;
296 op->stx=xop->extra;
297 break;
298 }
299 case TYPE_G: {
300 /* reg of ModR/M picks general register */
301 op->type=X86_OPTYPE_REG;
302 op->size=esizeop(xop->size);
303 op->reg=mkreg(getmodrm());
304 break;
305 }
306 case TYPE_Is: {
307 /* signed immediate */
308 op->type=X86_OPTYPE_IMM;
309 op->size=esizeop(xop->extendedsize);
310 int s=esizeop(xop->size);
311 switch (s) {
312 case 1:
313 op->imm=(char)getbyte();
314 break;
315 case 2:
316 op->imm=(short)getword();
317 break;
318 case 4:
319 op->imm=getdword();
320 break;
321 }
322 switch (op->size) {
323 case 1:
324 op->imm&=0xff;
325 break;
326 case 2:
327 op->imm&=0xffff;
328 break;
329 }
330 break;
331 }
332 case TYPE_I: {
333 /* unsigned immediate */
334 op->type=X86_OPTYPE_IMM;
335 op->size=esizeop(xop->extendedsize);
336 int s=esizeop(xop->size);
337 switch (s) {
338 case 1:
339 op->imm=getbyte();
340 break;
341 case 2:
342 op->imm=getword();
343 break;
344 case 4:
345 op->imm=getdword();
346 break;
347 }
348 break;
349 }
350 case TYPE_Ix: {
351 /* fixed immediate */
352 op->type=X86_OPTYPE_IMM;
353 op->size=esizeop(xop->extendedsize);
354 op->imm=xop->extra;
355 break;
356 }
357 case TYPE_J: {
358 /* relative branch offset */
359 op->type=X86_OPTYPE_IMM;
360 // op->size=esizeaddr(xop->extendedsize);
361 op->size=(addrsize==X86_ADDRSIZE32) ? 4 : 2;
362 int s=esizeop(xop->size);
363 switch (s) {
364 case 1:
365 op->imm=(char)getbyte()+addr;
366 break;
367 case 2:
368 op->imm=(short)getword()+addr;
369 break;
370 case 4:
371 op->imm=getdword()+addr;
372 break;
373 }
374 break;
375 }
376 case TYPE_M: {
377 /* ModR/M (memory only) */
378 decode_modrm(op, xop->size, 0, 1, 0);
379 break;
380 }
381 case TYPE_O: {
382 /* direct memory without ModR/M */
383 op->type=X86_OPTYPE_MEM;
384 op->size=esizeop(xop->size);
385 op->mem.floatptr=isfloat(xop->size);
386 op->mem.addrsize=insn.eaddrsize;
387 switch (insn.eaddrsize) {
388 case X86_ADDRSIZE16:
389 op->mem.hasdisp=1;
390 op->mem.disp=getword();
391 break;
392 case X86_ADDRSIZE32:
393 op->mem.hasdisp=1;
394 op->mem.disp=getdword();
395 break;
396 }
397 op->mem.base=X86_REG_NO;
398 op->mem.index=X86_REG_NO;
399 op->mem.scale=1;
400 break;
401 }
402 case TYPE_P: {
403 /* reg of ModR/M picks MMX register */
404 op->type=X86_OPTYPE_MMX;
405 op->size=8;
406 op->mmx=mkreg(getmodrm());
407 break;
408 }
409 case TYPE_Q: {
410 /* ModR/M (MMX reg or memory) */
411 decode_modrm(op, xop->size, 1, 1, 1);
412 break;
413 }
414 case TYPE_R: {
415 /* rm of ModR/M picks general register */
416 op->type=X86_OPTYPE_REG;
417 op->size=esizeop(xop->size);
418 op->reg=mkrm(getmodrm());
419 break;
420 }
421 case TYPE_Rx: {
422 /* extra picks register */
423 op->type=X86_OPTYPE_REG;
424 op->size=esizeop(xop->size);
425 op->reg=xop->extra;
426 break;
427 }
428 case TYPE_S: {
429 /* reg of ModR/M picks segment register */
430 op->type=X86_OPTYPE_SEG;
431 op->size=esizeop(xop->size);
432 op->seg=mkreg(getmodrm());
433 if (op->seg>5) invalidate();
434 break;
435 }
436 case TYPE_Sx: {
437 /* extra picks segment register */
438 op->type=X86_OPTYPE_SEG;
439 op->size=esizeop(xop->size);
440 op->seg=xop->extra;
441 if (op->seg>5) invalidate();
442 break;
443 }
444 case TYPE_T: {
445 /* reg of ModR/M picks test register */
446 op->type=X86_OPTYPE_TRX;
447 op->size=esizeop(xop->size);
448 op->trx=mkreg(getmodrm());
449 break;
450 }
451 }
452 }
453
454 void X86Disassembler::decode_sib(x86_insn_op *op, int mod)
455 {
456 int sib=getsib();
457 int scale=mkscale(sib);
458 int index=mkindex(sib);
459 int base=mkbase(sib);
460 int disp=mod;
461 if (base==5) {
462 if (mod==0) {
463 op->mem.base=X86_REG_NO;
464 disp=2;
465 } else {
466 op->mem.base=X86_REG_BP;
467 }
468 op->mem.index=sibindex[index];
469 op->mem.scale=sibscale[scale];
470 } else {
471 op->mem.base=sibbase[base];
472 op->mem.index=sibindex[index];
473 op->mem.scale=sibscale[scale];
474 }
475 switch (disp) {
476 case 0:
477 op->mem.hasdisp=0;
478 op->mem.disp=0;
479 break;
480 case 1:
481 op->mem.hasdisp=1;
482 op->mem.disp=(char)getbyte();
483 break;
484 case 2:
485 op->mem.hasdisp=1;
486 op->mem.disp=getdword();
487 break;
488 }
489 }
490
491 dis_insn *X86Disassembler::duplicateInsn(dis_insn *disasm_insn)
492 {
493 x86dis_insn *insn = (x86dis_insn *)malloc(sizeof (x86dis_insn));
494 *insn = *(x86dis_insn *)disasm_insn;
495 return insn;
496 }
497
498 int X86Disassembler::esizeaddr(char c)
499 {
500 switch (c) {
501 case SIZE_B:
502 return 1;
503 case SIZE_W:
504 return 2;
505 case SIZE_D:
506 return 4;
507 case SIZE_Q:
508 return 8;
509 case SIZE_S:
510 return 4;
511 case SIZE_L:
512 return 8;
513 case SIZE_T:
514 return 10;
515 case SIZE_C:
516 if (insn.eaddrsize==X86_ADDRSIZE16) return 1; else return 2;
517 case SIZE_V:
518 if (insn.eaddrsize==X86_ADDRSIZE16) return 2; else return 4;
519 case SIZE_P:
520 if (insn.eaddrsize==X86_ADDRSIZE16) return 4; else return 6;
521 }
522 return 0;
523 }
524
525 int X86Disassembler::esizeop(char c)
526 {
527 switch (c) {
528 case SIZE_B:
529 return 1;
530 case SIZE_W:
531 return 2;
532 case SIZE_D:
533 return 4;
534 case SIZE_Q:
535 return 8;
536 case SIZE_S:
537 return 4;
538 case SIZE_L:
539 return 8;
540 case SIZE_T:
541 return 10;
542 case SIZE_C:
543 if (insn.eopsize==X86_OPSIZE16) return 1; else return 2;
544 case SIZE_V:
545 if (insn.eopsize==X86_OPSIZE16) return 2; else return 4;
546 case SIZE_P:
547 if (insn.eopsize==X86_OPSIZE16) return 4; else return 6;
548 }
549 return 0;
550 }
551
552 byte X86Disassembler::getbyte()
553 {
554 if (codep-ocodep+1<=maxlen) {
555 addr+=1;
556 return *(codep++);
557 } else {
558 invalidate();
559 return 0;
560 }
561 }
562
563 word X86Disassembler::getword()
564 {
565 if (codep-ocodep+2<=maxlen) {
566 word w;
567 addr += 2;
568 w = codep[0] | (codep[1]<<8);
569 codep += 2;
570 return w;
571 } else {
572 invalidate();
573 return 0;
574 }
575 }
576
577 dword X86Disassembler::getdword()
578 {
579 if (codep-ocodep+4<=maxlen) {
580 dword w;
581 addr += 4;
582 w = codep[0] | (codep[1]<<8) | (codep[2]<<16) | (codep[3]<<24);
583 codep += 4;
584 return w;
585 } else {
586 invalidate();
587 return 0;
588 }
589 }
590
591 void X86Disassembler::getOpcodeMetrics(int &min_length, int &max_length, int &min_look_ahead, int &avg_look_ahead, int &addr_align)
592 {
593 min_length = 1;
594 max_length = 15;
595 min_look_ahead = 120; // 1/2/3/4/5/6/8/10/12/15
596 avg_look_ahead = 24; // 1/2/3/4/6/8/12/24
597 addr_align = 1;
598 }
599
600 int X86Disassembler::getmodrm()
601 {
602 if (modrm==-1) modrm=getbyte();
603 return modrm;
604 }
605
606 char *X86Disassembler::getName()
607 {
608 return "x86/Disassembler";
609 }
610
611 int X86Disassembler::getsib()
612 {
613 if (sib==-1) sib=getbyte();
614 return sib;
615 }
616
617 byte X86Disassembler::getSize(dis_insn *disasm_insn)
618 {
619 return ((x86dis_insn*)disasm_insn)->size;
620 }
621
622 void X86Disassembler::invalidate()
623 {
624 insn.invalid=1;
625 }
626
627 int X86Disassembler::isfloat(char c)
628 {
629 switch (c) {
630 case SIZE_S:
631 case SIZE_L:
632 case SIZE_T:
633 return 1;
634 }
635 return 0;
636 }
637
638 void X86Disassembler::prefixes()
639 {
640 bool notprefix=0;
641 insn.lockprefix=X86_PREFIX_NO;
642 insn.repprefix=X86_PREFIX_NO;
643 insn.segprefix=X86_PREFIX_NO;
644 while ((codep-ocodep<15) && (!notprefix)) {
645 c=getbyte();
646 switch (c) {
647 case 0x26:
648 insn.segprefix=X86_PREFIX_ES;
649 break;
650 case 0x2e:
651 insn.segprefix=X86_PREFIX_CS;
652 break;
653 case 0x36:
654 insn.segprefix=X86_PREFIX_SS;
655 break;
656 case 0x3e:
657 insn.segprefix=X86_PREFIX_DS;
658 break;
659 case 0x64:
660 insn.segprefix=X86_PREFIX_FS;
661 break;
662 case 0x65:
663 insn.segprefix=X86_PREFIX_GS;
664 break;
665 case 0x66:
666 insn.eopsize=(opsize==X86_OPSIZE16) ? X86_OPSIZE32 : X86_OPSIZE16;
667 break;
668 case 0x67:
669 insn.eaddrsize=(addrsize==X86_ADDRSIZE16) ? X86_ADDRSIZE32 : X86_ADDRSIZE16;
670 break;
671 case 0xf0:
672 insn.lockprefix=X86_PREFIX_LOCK;
673 break;
674 case 0xf2:
675 insn.repprefix=X86_PREFIX_REPNZ;
676 break;
677 case 0xf3:
678 insn.repprefix=X86_PREFIX_REPZ;
679 break;
680 default:
681 notprefix=1;
682 }
683 }
684 }
685
686 int X86Disassembler::special_param_ambiguity(x86dis_insn *disasm_insn)
687 {
688 int regc=0, memc=0, segc=0;
689 for (int i=0; i<3; i++) {
690 switch (disasm_insn->op[i].type) {
691 case X86_OPTYPE_SEG:
692 segc++;
693 case X86_OPTYPE_REG:
694 case X86_OPTYPE_CRX:
695 case X86_OPTYPE_DRX:
696 case X86_OPTYPE_TRX:
697 case X86_OPTYPE_STX:
698 case X86_OPTYPE_MMX:
699 regc++;
700 break;
701 case X86_OPTYPE_MEM:
702 memc++;
703 break;
704 }
705 }
706 return (memc && !regc)
707 || (memc && segc)
708 || (strcmp(disasm_insn->name, "movzx") == 0)
709 || (strcmp(disasm_insn->name, "movsx") == 0);
710 }
711
712 void X86Disassembler::str_op(char *opstr, int *opstrlen, x86dis_insn *insn, x86_insn_op *op, bool explicit_params)
713 {
714 const char *cs_default = get_cs(e_cs_default);
715 const char *cs_number = get_cs(e_cs_number);
716 const char *cs_symbol = get_cs(e_cs_symbol);
717
718 *opstrlen=0;
719 switch (op->type) {
720 case X86_OPTYPE_IMM: {
721 CPU_ADDR a;
722 // FIXME: hack
723 if ((insn->name[0]=='j') || strcmp(insn->name, "call")==0) {
724 a.addr32.seg = seg;
725 } else {
726 a.addr32.seg = 0;
727 }
728 a.addr32.offset = op->imm;
729 int slen;
730 char *s=(addr_sym_func) ? addr_sym_func(a, &slen, addr_sym_func_context) : NULL;
731 if (s) {
732 memmove(opstr, s, slen);
733 opstr[slen]=0;
734 *opstrlen=slen;
735 } else {
736 char *g=opstr;
737 strcpy(g, cs_number); g += strlen(cs_number);
738 switch (op->size) {
739 case 1:
740 hexd(&g, 2, options, op->imm);
741 break;
742 case 2:
743 hexd(&g, 4, options, op->imm);
744 break;
745 case 4:
746 hexd(&g, 8, options, op->imm);
747 break;
748 }
749 strcpy(g, cs_default); g += strlen(cs_default);
750 }
751 break;
752 }
753 case X86_OPTYPE_REG: {
754 int j;
755 switch (op->size) {
756 case 1: j=0; break;
757 case 2: j=1; break;
758 case 4: j=2; break;
759 default:
760 j=-1;
761 }
762 if (j!=-1) sprintf(opstr, x86_regs[j][op->reg]);
763 break;
764 }
765 case X86_OPTYPE_SEG:
766 if (x86_segs[op->seg]) {
767 sprintf(opstr, x86_segs[op->seg]);
768 }
769 break;
770 case X86_OPTYPE_CRX:
771 sprintf(opstr, "cr%d", op->crx);
772 break;
773 case X86_OPTYPE_DRX:
774 sprintf(opstr, "dr%d", op->drx);
775 break;
776 case X86_OPTYPE_TRX:
777 sprintf(opstr, "tr%d", op->trx);
778 break;
779 case X86_OPTYPE_STX:
780 if (op->stx) {
781 sprintf(opstr, "st(%d)", op->stx);
782 } else {
783 strcpy(opstr, "st");
784 }
785 break;
786 case X86_OPTYPE_MMX:
787 sprintf(opstr, "mm%d", op->mmx);
788 break;
789 case X86_OPTYPE_MEM: {
790 char *d=opstr;
791 int reg;
792 if (explicit_params) {
793 if (op->mem.floatptr) {
794 switch (op->size) {
795 case 4:
796 d+=sprintf(d, "single ptr ");
797 break;
798 case 8:
799 d+=sprintf(d, "double ptr ");
800 break;
801 case 10:
802 d+=sprintf(d, "extended ptr ");
803 break;
804 }
805 } else {
806 switch (op->size) {
807 case 1:
808 d+=sprintf(d, "byte ptr ");
809 break;
810 case 2:
811 d+=sprintf(d, "word ptr ");
812 break;
813 case 4:
814 d+=sprintf(d, "dword ptr ");
815 break;
816 case 6:
817 d+=sprintf(d, "pword ptr ");
818 break;
819 case 8:
820 d+=sprintf(d, "qword ptr ");
821 break;
822 }
823 }
824 }
825 if (insn->eaddrsize==X86_ADDRSIZE16) reg=1; else reg=2;
826 if (insn->segprefix!=X86_PREFIX_NO) d+=sprintf(d, "%s%s:%s", x86_segs[insn->segprefix], cs_symbol, cs_default);
827 strcpy(d, cs_symbol); d += strlen(cs_symbol);
828 *(d++)='[';
829 strcpy(d, cs_default); d += strlen(cs_default);
830
831 int optimize_addr=options & X86DIS_STYLE_OPTIMIZE_ADDR;
832 int first=1;
833 if (optimize_addr && (op->mem.base!=X86_REG_NO) && (op->mem.base==op->mem.index)) {
834 d+=sprintf(d, "%s%s*%s%d%s", x86_regs[reg][op->mem.index], cs_symbol, cs_number, op->mem.scale+1, cs_default);
835 first=0;
836 } else {
837 if (op->mem.base!=X86_REG_NO) {
838 d+=sprintf(d, "%s", x86_regs[reg][op->mem.base]);
839 first=0;
840 }
841 if (op->mem.index!=X86_REG_NO) {
842 if (!first) *(d++)='+';
843 if ((op->mem.scale==1)) {
844 d+=sprintf(d, "%s", x86_regs[reg][op->mem.index]);
845 } else {
846 d+=sprintf(d, "%s%s*%s%d%s", x86_regs[reg][op->mem.index], cs_symbol, cs_number, op->mem.scale, cs_default);
847 }
848 first=0;
849 }
850 }
851 if ((!optimize_addr && op->mem.hasdisp) || (optimize_addr && op->mem.disp) || first) {
852 CPU_ADDR a;
853 a.addr32.seg = 0; // FIXME: not ok
854 a.addr32.offset=op->mem.disp;
855 int slen;
856 char *s=(addr_sym_func) ? addr_sym_func(a, &slen, addr_sym_func_context) : 0;
857 if (s) {
858 if (!first) {
859 strcpy(d, cs_symbol); d += strlen(cs_symbol);
860 *(d++)='+';
861 strcpy(d, cs_default); d += strlen(cs_default);
862 }
863 memmove(d, s, slen);
864 d+=slen;
865 *opstrlen=d-opstr;
866 } else {
867 dword q;
868 switch (op->mem.addrsize) {
869 case X86_ADDRSIZE16:
870 q=op->mem.disp;
871 if (!first) {
872 strcpy(d, cs_symbol); d += strlen(cs_symbol);
873 if (op->mem.disp&0x80000000) {
874 *(d++)='-';
875 q=-q;
876 } else *(d++)='+';
877 }
878 strcpy(d, cs_number); d += strlen(cs_number);
879 hexd(&d, 4, options, q);
880 strcpy(d, cs_default); d += strlen(cs_default);
881 break;
882 case X86_ADDRSIZE32:
883 q=op->mem.disp;
884 if (!first) {
885 strcpy(d, cs_symbol); d += strlen(cs_symbol);
886 if (op->mem.disp&0x80000000) {
887 *(d++)='-';
888 q=-q;
889 } else *(d++)='+';
890 }
891 strcpy(d, cs_number); d += strlen(cs_number);
892 hexd(&d, 8, options, q);
893 strcpy(d, cs_default); d += strlen(cs_default);
894 break;
895 }
896 }
897 }
898 strcpy(d, cs_symbol); d += strlen(cs_symbol);
899 *(d++)=']';
900 strcpy(d, cs_default); d += strlen(cs_default);
901 if (*opstrlen)
902 *opstrlen += strlen(cs_symbol) + 1 + strlen(cs_default);
903 *d=0;
904 break;
905 }
906 case X86_OPTYPE_FARPTR: {
907 CPU_ADDR a;
908 /* a.addr32.seg = op->farptr.seg;
909 a.addr32.offset = op->farptr.offset;
910 */
911 a.addr32.seg = op->farptr.seg;
912 a.addr32.offset = op->farptr.offset;
913 int slen;
914 char *s=(addr_sym_func) ? addr_sym_func(a, &slen, addr_sym_func_context) : 0;
915 if (s) {
916 memmove(opstr, s, slen);
917 opstr[slen]=0;
918 *opstrlen=slen;
919 } else {
920 char *g=opstr;
921 hexd(&g, 4, options, op->farptr.seg);
922 strcpy(g, cs_symbol); g += strlen(cs_symbol);
923 *(g++)=':';
924 strcpy(g, cs_default); g += strlen(cs_default);
925 switch (op->size) {
926 case 4:
927 hexd(&g, 4, options, op->farptr.offset);
928 break;
929 case 6:
930 hexd(&g, 8, options, op->farptr.offset);
931 break;
932 }
933 }
934 break;
935 }
936 default:
937 opstr[0]=0;
938 }
939 }
940
941 void X86Disassembler::str_format(char **str, char **format, char *p, char *n, char *op[3], int oplen[3], char stopchar, int print)
942 {
943 const char *cs_default = get_cs(e_cs_default);
944 const char *cs_symbol = get_cs(e_cs_symbol);
945
946 char *f=*format;
947 char *s=*str;
948 while (*f) {
949 if (*f==stopchar) break;
950 switch (*f) {
951 case '\t':
952 if (print) do *(s++)=' '; while ((s-insnstr) % DIS_STYLE_TABSIZE);
953 break;
954 case DISASM_STRF_VAR:
955 f++;
956 if (print) {
957 char *t=0;
958 int tl=0;
959 switch (*f) {
960 case DISASM_STRF_PREFIX:
961 t=p;
962 break;
963 case DISASM_STRF_NAME:
964 t=n;
965 break;
966 case DISASM_STRF_FIRST:
967 t=op[0];
968 tl=oplen[0];
969 break;
970 case DISASM_STRF_SECOND:
971 t=op[1];
972 tl=oplen[1];
973 break;
974 case DISASM_STRF_THIRD:
975 t=op[2];
976 tl=oplen[2];
977 break;
978 }
979 if (tl) {
980 memmove(s, t, tl);
981 s+=tl;
982 *s=0;
983 } else {
984 strcpy(s, t);
985 s += strlen(s);
986 }
987 }
988 break;
989 case DISASM_STRF_COND: {
990 char *t=0;
991 f++;
992 switch (*f) {
993 case DISASM_STRF_PREFIX:
994 t=p;
995 break;
996 case DISASM_STRF_NAME:
997 t=n;
998 break;
999 case DISASM_STRF_FIRST:
1000 t=op[0];
1001 break;
1002 case DISASM_STRF_SECOND:
1003 t=op[1];
1004 break;
1005 case DISASM_STRF_THIRD:
1006 t=op[2];
1007 break;
1008 }
1009 f+=2;
1010 if ((t) && (t[0])) {
1011 str_format(&s, &f, p, n, op, oplen, *(f-1), 1);
1012 } else {
1013 str_format(&s, &f, p, n, op, oplen, *(f-1), 0);
1014 }
1015 break;
1016 }
1017 default:
1018 if (print) {
1019 bool x = (strchr(",.-=+-*/[]()", *f) != NULL) && *f;
1020 if (x) { strcpy(s, cs_symbol); s += strlen(cs_symbol); }
1021 *(s++) = *f;
1022 if (x) { strcpy(s, cs_default); s += strlen(cs_default); }
1023 }
1024 }
1025 f++;
1026 }
1027 *s=0;
1028 *format=f;
1029 *str=s;
1030 }
1031
1032 char *X86Disassembler::str(dis_insn *disasm_insn, int options)
1033 {
1034 return strf(disasm_insn, options, DISASM_STRF_DEFAULT_FORMAT);
1035 }
1036
1037 char *X86Disassembler::strf(dis_insn *disasm_insn, int opt, char *format)
1038 {
1039 x86dis_insn *insn = (x86dis_insn*)disasm_insn;
1040 char prefix[64];
1041 char *p = prefix;
1042 options = opt;
1043 *p = 0;
1044 if (insn->lockprefix == X86_PREFIX_LOCK) p+=sprintf(p, "lock ");
1045 if (insn->repprefix == X86_PREFIX_REPZ) {
1046 p += sprintf(p, "repz ");
1047 } else if (insn->repprefix == X86_PREFIX_REPNZ) {
1048 p += sprintf(p, "repnz ");
1049 }
1050 if ((p != prefix) && (*(p-1) == ' ')) {
1051 p--;
1052 *p = 0;
1053 }
1054
1055 bool explicit_params = ((options & X86DIS_STYLE_EXPLICIT_MEMSIZE) ||
1056 special_param_ambiguity(insn));
1057
1058 char ops[3][512]; /* FIXME: possible buffer overflow ! */
1059 char *op[3];
1060 int oplen[3];
1061
1062 if (options & DIS_STYLE_HIGHLIGHT) enable_highlighting();
1063 for (int i=0; i<3; i++) {
1064 op[i]=(char*)&ops[i];
1065 str_op(op[i], &oplen[i], insn, &insn->op[i], explicit_params);
1066 }
1067 char *s=insnstr;
1068 char n[32];
1069 switch (insn->eopsize) {
1070 case X86_OPSIZE16:
1071 sprintf(n, insn->name, 'w');
1072 break;
1073 case X86_OPSIZE32:
1074 sprintf(n, insn->name, 'd');
1075 break;
1076 default:
1077 strcpy(n, insn->name);
1078 break;
1079 }
1080 str_format(&s, &format, prefix, n, op, oplen, 0, 1);
1081 disable_highlighting();
1082 return insnstr;
1083 }
1084
1085 bool X86Disassembler::validInsn(dis_insn *disasm_insn)
1086 {
1087 return !((x86dis_insn *)disasm_insn)->invalid;
1088 }
1089

  ViewVC Help
Powered by ViewVC 1.1.26