/[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

Annotation of /src/debug/x86dis.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (hide 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 dpavlin 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