00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "stream.h"
00022 #include "store.h"
00023 #include "tools.h"
00024 #include "vxd.h"
00025 #include "x86dis.h"
00026
00027 #include <stdio.h>
00028 #include <string.h>
00029
00030 #define mkmod(modrm) (((modrm)>>6)&3)
00031 #define mkreg(modrm) (((modrm)>>3)&7)
00032 #define mkrm(modrm) ((modrm)&7)
00033
00034 #define mkscale(modrm) (((modrm)>>6)&3)
00035 #define mkindex(modrm) (((modrm)>>3)&7)
00036 #define mkbase(modrm) ((modrm)&7)
00037
00038 int modrm16_1[8] = { X86_REG_BX, X86_REG_BX, X86_REG_BP, X86_REG_BP,
00039 X86_REG_SI, X86_REG_DI, X86_REG_BP, X86_REG_BX};
00040 int modrm16_2[8] = { X86_REG_SI, X86_REG_DI, X86_REG_SI, X86_REG_DI,
00041 X86_REG_NO, X86_REG_NO, X86_REG_NO, X86_REG_NO};
00042
00043 int sibbase[8] = { X86_REG_AX, X86_REG_CX, X86_REG_DX, X86_REG_BX,
00044 X86_REG_SP, X86_REG_BP, X86_REG_SI, X86_REG_DI };
00045
00046 int sibindex[8] = { X86_REG_AX, X86_REG_CX, X86_REG_DX, X86_REG_BX,
00047 X86_REG_NO, X86_REG_BP, X86_REG_SI, X86_REG_DI };
00048
00049 int sibscale[4] = {1, 2, 4, 8};
00050
00051
00052
00053
00054
00055 x86dis::x86dis()
00056 {
00057 }
00058
00059 x86dis::x86dis(int _opsize, int _addrsize)
00060 {
00061 opsize=_opsize;
00062 addrsize=_addrsize;
00063 }
00064
00065 x86dis::~x86dis()
00066 {
00067 }
00068
00069 dis_insn *x86dis::decode(byte *code, int Maxlen, CPU_ADDR Addr)
00070 {
00071 ocodep=code;
00072
00073 codep=ocodep;
00074 maxlen=Maxlen;
00075 seg=Addr.addr32.seg;
00076 addr=Addr.addr32.offset;
00077 modrm=-1;
00078 sib=-1;
00079 memset(&insn, 0, sizeof(insn));
00080 insn.invalid=false;
00081 insn.eopsize=opsize;
00082 insn.eaddrsize=opsize;
00083
00084 prefixes();
00085
00086 insn.opcode=c;
00087 decode_insn(&x86_insns[insn.opcode]);
00088
00089 if (insn.invalid) {
00090 insn.name="db";
00091 insn.size=1;
00092 insn.op[0].type=X86_OPTYPE_IMM;
00093 insn.op[0].size=1;
00094 insn.op[0].imm=*code;
00095 insn.lockprefix=X86_PREFIX_NO;
00096 insn.repprefix=X86_PREFIX_NO;
00097 insn.segprefix=X86_PREFIX_NO;
00098 for (int i=1; i<3; i++) insn.op[i].type=X86_OPTYPE_EMPTY;
00099 } else {
00100 insn.size=codep-ocodep;
00101 }
00102 return &insn;
00103 }
00104
00105 void x86dis::decode_modrm(x86_insn_op *op, char size, int allow_reg, int allow_mem, int mmx)
00106 {
00107 int modrm=getmodrm();
00108 int mod=mkmod(modrm);
00109 int rm=mkrm(modrm);
00110 if (mod==3) {
00111
00112 if (!allow_reg) {
00113 invalidate();
00114 return;
00115 }
00116 if (mmx) {
00117 op->type=X86_OPTYPE_MMX;
00118 op->size=8;
00119 op->mmx=rm;
00120 } else {
00121 op->type=X86_OPTYPE_REG;
00122 op->size=esizeop(size);
00123 op->reg=rm;
00124 }
00125 } else {
00126
00127 if (!allow_mem) {
00128 invalidate();
00129 return;
00130 }
00131 op->mem.addrsize=insn.eaddrsize;
00132 if (insn.eaddrsize==X86_ADDRSIZE16) {
00133 op->type=X86_OPTYPE_MEM;
00134 op->size=esizeop(size);
00135 op->mem.floatptr=isfloat(size);
00136 if ((mod==0) && (rm==6)) {
00137 op->mem.hasdisp=1;
00138 op->mem.disp=getword();
00139 op->mem.base=X86_REG_NO;
00140 op->mem.index=X86_REG_NO;
00141 op->mem.scale=0;
00142 } else {
00143 op->mem.base=modrm16_1[rm];
00144 op->mem.index=modrm16_2[rm];
00145 op->mem.scale=1;
00146 switch (mod) {
00147 case 0:
00148 op->mem.hasdisp=0;
00149 op->mem.disp=0;
00150 break;
00151 case 1:
00152 op->mem.hasdisp=1;
00153 op->mem.disp=(char)getbyte();
00154 break;
00155 case 2:
00156 op->mem.hasdisp=1;
00157 op->mem.disp=(short)getword();
00158 break;
00159 }
00160 }
00161 } else {
00162 op->type=X86_OPTYPE_MEM;
00163 op->size=esizeop(size);
00164 op->mem.floatptr=isfloat(size);
00165 if ((mod==0) && (rm==5)) {
00166 op->mem.hasdisp=1;
00167 op->mem.disp=getdword();
00168 op->mem.base=X86_REG_NO;
00169 op->mem.index=X86_REG_NO;
00170 op->mem.scale=0;
00171 } else if (rm==4) {
00172 decode_sib(op, mod);
00173 } else {
00174 op->mem.base=rm;
00175 op->mem.index=X86_REG_NO;
00176 op->mem.scale=1;
00177 switch (mod) {
00178 case 0:
00179 op->mem.hasdisp=0;
00180 op->mem.disp=0;
00181 break;
00182 case 1:
00183 op->mem.hasdisp=1;
00184 op->mem.disp=(char)getbyte();
00185 break;
00186 case 2:
00187 op->mem.hasdisp=1;
00188 op->mem.disp=getdword();
00189 break;
00190 }
00191 }
00192 }
00193 }
00194 }
00195
00196 void x86dis::decode_insn(x86opc_insn *xinsn)
00197 {
00198 if (!xinsn->name) {
00199 x86opc_insn_op_special special=*((x86opc_insn_op_special*)(&xinsn->op[0]));
00200 switch (special.type) {
00201 case SPECIAL_TYPE_INVALID:
00202 invalidate();
00203 break;
00204 case SPECIAL_TYPE_PREFIX:
00205 switch (c) {
00206 case 0x0f:
00207 if (insn.opcodeclass == X86DIS_OPCODE_CLASS_STD) {
00208 insn.opcode = getbyte();
00209 insn.opcodeclass = X86DIS_OPCODE_CLASS_EXT;
00210 decode_insn(&x86_insns_ext[insn.opcode]);
00211 break;
00212 }
00213 default:
00214 invalidate();
00215 break;
00216 }
00217 break;
00218 case SPECIAL_TYPE_GROUP: {
00219 int m = mkreg(getmodrm());
00220 insn.opcode |= m<<8;
00221 decode_insn(&x86_group_insns[(int)special.data][m]);
00222 break;
00223 }
00224 case SPECIAL_TYPE_FGROUP: {
00225 int m = getmodrm();
00226 if (mkmod(m) == 3) {
00227 x86opc_finsn f = x86_float_group_insns[(int)special.data][mkreg(m)];
00228
00229 if (f.group) {
00230 decode_insn(&f.group[mkrm(m)]);
00231 } else if (f.insn.name) {
00232 decode_insn(&f.insn);
00233 } else invalidate();
00234 } else {
00235 decode_insn(&x86_modfloat_group_insns[(int)special.data][mkreg(m)]);
00236 }
00237 break;
00238 }
00239 }
00240 } else {
00241 insn.name=xinsn->name;
00242 for (int i=0; i<3; i++) {
00243 decode_op(&insn.op[i], &xinsn->op[i]);
00244 }
00245 }
00246 }
00247
00248 void x86dis::decode_op(x86_insn_op *op, x86opc_insn_op *xop)
00249 {
00250 switch (xop->type) {
00251 case TYPE_0:
00252 return;
00253 case TYPE_A: {
00254
00255 op->type=X86_OPTYPE_FARPTR;
00256 op->size=esizeop(xop->size);
00257 switch (op->size) {
00258 case 4:
00259 op->farptr.offset=getword();
00260 op->farptr.seg=getword();
00261 break;
00262 case 6:
00263 op->farptr.offset=getdword();
00264 op->farptr.seg=getword();
00265 break;
00266 }
00267 break;
00268 }
00269 case TYPE_C: {
00270
00271 op->type=X86_OPTYPE_CRX;
00272 op->size=esizeop(xop->size);
00273 op->crx=mkreg(getmodrm());
00274 break;
00275 }
00276 case TYPE_D: {
00277
00278 op->type=X86_OPTYPE_DRX;
00279 op->size=esizeop(xop->size);
00280 op->drx=mkreg(getmodrm());
00281 break;
00282 }
00283 case TYPE_E: {
00284
00285 decode_modrm(op, xop->size, (xop->size!=SIZE_P), 1, 0);
00286 break;
00287 }
00288 case TYPE_F: {
00289
00290 op->type=X86_OPTYPE_STX;
00291 op->size=10;
00292 op->stx=mkrm(getmodrm());
00293 break;
00294 }
00295 case TYPE_Fx: {
00296
00297 op->type=X86_OPTYPE_STX;
00298 op->size=10;
00299 op->stx=xop->extra;
00300 break;
00301 }
00302 case TYPE_G: {
00303
00304 op->type=X86_OPTYPE_REG;
00305 op->size=esizeop(xop->size);
00306 op->reg=mkreg(getmodrm());
00307 break;
00308 }
00309 case TYPE_Is: {
00310
00311 op->type=X86_OPTYPE_IMM;
00312 op->size=esizeop(xop->extendedsize);
00313 int s=esizeop(xop->size);
00314 switch (s) {
00315 case 1:
00316 op->imm=(char)getbyte();
00317 break;
00318 case 2:
00319 op->imm=(short)getword();
00320 break;
00321 case 4:
00322 op->imm=getdword();
00323 break;
00324 }
00325 switch (op->size) {
00326 case 1:
00327 op->imm&=0xff;
00328 break;
00329 case 2:
00330 op->imm&=0xffff;
00331 break;
00332 }
00333 break;
00334 }
00335 case TYPE_I: {
00336
00337 op->type=X86_OPTYPE_IMM;
00338 op->size=esizeop(xop->extendedsize);
00339 int s=esizeop(xop->size);
00340 switch (s) {
00341 case 1:
00342 op->imm=getbyte();
00343 break;
00344 case 2:
00345 op->imm=getword();
00346 break;
00347 case 4:
00348 op->imm=getdword();
00349 break;
00350 }
00351 break;
00352 }
00353 case TYPE_Ix: {
00354
00355 op->type=X86_OPTYPE_IMM;
00356 op->size=esizeop(xop->extendedsize);
00357 op->imm=xop->extra;
00358 break;
00359 }
00360 case TYPE_J: {
00361
00362 op->type=X86_OPTYPE_IMM;
00363
00364 op->size=(addrsize==X86_ADDRSIZE32) ? 4 : 2;
00365 int s=esizeop(xop->size);
00366 switch (s) {
00367 case 1:
00368 op->imm=(char)getbyte()+addr;
00369 break;
00370 case 2:
00371 op->imm=(short)getword()+addr;
00372 break;
00373 case 4:
00374 op->imm=getdword()+addr;
00375 break;
00376 }
00377 break;
00378 }
00379 case TYPE_M: {
00380
00381 decode_modrm(op, xop->size, 0, 1, 0);
00382 break;
00383 }
00384 case TYPE_O: {
00385
00386 op->type=X86_OPTYPE_MEM;
00387 op->size=esizeop(xop->size);
00388 op->mem.floatptr=isfloat(xop->size);
00389 op->mem.addrsize=insn.eaddrsize;
00390 switch (insn.eaddrsize) {
00391 case X86_ADDRSIZE16:
00392 op->mem.hasdisp=1;
00393 op->mem.disp=getword();
00394 break;
00395 case X86_ADDRSIZE32:
00396 op->mem.hasdisp=1;
00397 op->mem.disp=getdword();
00398 break;
00399 }
00400 op->mem.base=X86_REG_NO;
00401 op->mem.index=X86_REG_NO;
00402 op->mem.scale=1;
00403 break;
00404 }
00405 case TYPE_P: {
00406
00407 op->type=X86_OPTYPE_MMX;
00408 op->size=8;
00409 op->mmx=mkreg(getmodrm());
00410 break;
00411 }
00412 case TYPE_Q: {
00413
00414 decode_modrm(op, xop->size, 1, 1, 1);
00415 break;
00416 }
00417 case TYPE_R: {
00418
00419 op->type=X86_OPTYPE_REG;
00420 op->size=esizeop(xop->size);
00421 op->reg=mkrm(getmodrm());
00422 break;
00423 }
00424 case TYPE_Rx: {
00425
00426 op->type=X86_OPTYPE_REG;
00427 op->size=esizeop(xop->size);
00428 op->reg=xop->extra;
00429 break;
00430 }
00431 case TYPE_S: {
00432
00433 op->type=X86_OPTYPE_SEG;
00434 op->size=esizeop(xop->size);
00435 op->seg=mkreg(getmodrm());
00436 if (op->seg>5) invalidate();
00437 break;
00438 }
00439 case TYPE_Sx: {
00440
00441 op->type=X86_OPTYPE_SEG;
00442 op->size=esizeop(xop->size);
00443 op->seg=xop->extra;
00444 if (op->seg>5) invalidate();
00445 break;
00446 }
00447 case TYPE_T: {
00448
00449 op->type=X86_OPTYPE_TRX;
00450 op->size=esizeop(xop->size);
00451 op->trx=mkreg(getmodrm());
00452 break;
00453 }
00454 }
00455 }
00456
00457 void x86dis::decode_sib(x86_insn_op *op, int mod)
00458 {
00459 int sib=getsib();
00460 int scale=mkscale(sib);
00461 int index=mkindex(sib);
00462 int base=mkbase(sib);
00463 int disp=mod;
00464 if (base==5) {
00465 if (mod==0) {
00466 op->mem.base=X86_REG_NO;
00467 disp=2;
00468 } else {
00469 op->mem.base=X86_REG_BP;
00470 }
00471 op->mem.index=sibindex[index];
00472 op->mem.scale=sibscale[scale];
00473 } else {
00474 op->mem.base=sibbase[base];
00475 op->mem.index=sibindex[index];
00476 op->mem.scale=sibscale[scale];
00477 }
00478 switch (disp) {
00479 case 0:
00480 op->mem.hasdisp=0;
00481 op->mem.disp=0;
00482 break;
00483 case 1:
00484 op->mem.hasdisp=1;
00485 op->mem.disp=(char)getbyte();
00486 break;
00487 case 2:
00488 op->mem.hasdisp=1;
00489 op->mem.disp=getdword();
00490 break;
00491 }
00492 }
00493
00494 dis_insn *x86dis::duplicateInsn(dis_insn *disasm_insn)
00495 {
00496 x86dis_insn *insn = (x86dis_insn *)malloc(sizeof (x86dis_insn));
00497 *insn = *(x86dis_insn *)disasm_insn;
00498 return insn;
00499 }
00500
00501 int x86dis::esizeaddr(char c)
00502 {
00503 switch (c) {
00504 case SIZE_B:
00505 return 1;
00506 case SIZE_W:
00507 return 2;
00508 case SIZE_D:
00509 return 4;
00510 case SIZE_Q:
00511 return 8;
00512 case SIZE_S:
00513 return 4;
00514 case SIZE_L:
00515 return 8;
00516 case SIZE_T:
00517 return 10;
00518 case SIZE_C:
00519 if (insn.eaddrsize==X86_ADDRSIZE16) return 1; else return 2;
00520 case SIZE_V:
00521 if (insn.eaddrsize==X86_ADDRSIZE16) return 2; else return 4;
00522 case SIZE_P:
00523 if (insn.eaddrsize==X86_ADDRSIZE16) return 4; else return 6;
00524 }
00525 return 0;
00526 }
00527
00528 int x86dis::esizeop(char c)
00529 {
00530 switch (c) {
00531 case SIZE_B:
00532 return 1;
00533 case SIZE_W:
00534 return 2;
00535 case SIZE_D:
00536 return 4;
00537 case SIZE_Q:
00538 return 8;
00539 case SIZE_S:
00540 return 4;
00541 case SIZE_L:
00542 return 8;
00543 case SIZE_T:
00544 return 10;
00545 case SIZE_C:
00546 if (insn.eopsize==X86_OPSIZE16) return 1; else return 2;
00547 case SIZE_V:
00548 if (insn.eopsize==X86_OPSIZE16) return 2; else return 4;
00549 case SIZE_P:
00550 if (insn.eopsize==X86_OPSIZE16) return 4; else return 6;
00551 }
00552 return 0;
00553 }
00554
00555 byte x86dis::getbyte()
00556 {
00557 if (codep-ocodep+1<=maxlen) {
00558 addr+=1;
00559 return *(codep++);
00560 } else {
00561 invalidate();
00562 return 0;
00563 }
00564 }
00565
00566 word x86dis::getword()
00567 {
00568 if (codep-ocodep+2<=maxlen) {
00569 word w;
00570 addr += 2;
00571 w = codep[0] | (codep[1]<<8);
00572 codep += 2;
00573 return w;
00574 } else {
00575 invalidate();
00576 return 0;
00577 }
00578 }
00579
00580 dword x86dis::getdword()
00581 {
00582 if (codep-ocodep+4<=maxlen) {
00583 dword w;
00584 addr += 4;
00585 w = codep[0] | (codep[1]<<8) | (codep[2]<<16) | (codep[3]<<24);
00586 codep += 4;
00587 return w;
00588 } else {
00589 invalidate();
00590 return 0;
00591 }
00592 }
00593
00594 void x86dis::getOpcodeMetrics(int &min_length, int &max_length, int &min_look_ahead, int &avg_look_ahead, int &addr_align)
00595 {
00596 min_length = 1;
00597 max_length = 15;
00598 min_look_ahead = 120;
00599 avg_look_ahead = 24;
00600 addr_align = 1;
00601 }
00602
00603 int x86dis::getmodrm()
00604 {
00605 if (modrm==-1) modrm=getbyte();
00606 return modrm;
00607 }
00608
00609 char *x86dis::getName()
00610 {
00611 return "x86/Disassembler";
00612 }
00613
00614 int x86dis::getsib()
00615 {
00616 if (sib==-1) sib=getbyte();
00617 return sib;
00618 }
00619
00620 byte x86dis::getSize(dis_insn *disasm_insn)
00621 {
00622 return ((x86dis_insn*)disasm_insn)->size;
00623 }
00624
00625 void x86dis::invalidate()
00626 {
00627 insn.invalid=1;
00628 }
00629
00630 int x86dis::isfloat(char c)
00631 {
00632 switch (c) {
00633 case SIZE_S:
00634 case SIZE_L:
00635 case SIZE_T:
00636 return 1;
00637 }
00638 return 0;
00639 }
00640
00641 int x86dis::load(ht_object_stream *f)
00642 {
00643 GET_INT_HEX(f, opsize);
00644 GET_INT_HEX(f, addrsize);
00645 return f->get_error();
00646 }
00647
00648 OBJECT_ID x86dis::object_id() const
00649 {
00650 return ATOM_DISASM_X86;
00651 }
00652
00653 void x86dis::prefixes()
00654 {
00655 bool notprefix=0;
00656 insn.lockprefix=X86_PREFIX_NO;
00657 insn.repprefix=X86_PREFIX_NO;
00658 insn.segprefix=X86_PREFIX_NO;
00659 while ((codep-ocodep<15) && (!notprefix)) {
00660 c=getbyte();
00661 switch (c) {
00662 case 0x26:
00663 insn.segprefix=X86_PREFIX_ES;
00664 break;
00665 case 0x2e:
00666 insn.segprefix=X86_PREFIX_CS;
00667 break;
00668 case 0x36:
00669 insn.segprefix=X86_PREFIX_SS;
00670 break;
00671 case 0x3e:
00672 insn.segprefix=X86_PREFIX_DS;
00673 break;
00674 case 0x64:
00675 insn.segprefix=X86_PREFIX_FS;
00676 break;
00677 case 0x65:
00678 insn.segprefix=X86_PREFIX_GS;
00679 break;
00680 case 0x66:
00681 insn.eopsize=(opsize==X86_OPSIZE16) ? X86_OPSIZE32 : X86_OPSIZE16;
00682 break;
00683 case 0x67:
00684 insn.eaddrsize=(addrsize==X86_ADDRSIZE16) ? X86_ADDRSIZE32 : X86_ADDRSIZE16;
00685 break;
00686 case 0xf0:
00687 insn.lockprefix=X86_PREFIX_LOCK;
00688 break;
00689 case 0xf2:
00690 insn.repprefix=X86_PREFIX_REPNZ;
00691 break;
00692 case 0xf3:
00693 insn.repprefix=X86_PREFIX_REPZ;
00694 break;
00695 default:
00696 notprefix=1;
00697 }
00698 }
00699 }
00700
00701 int x86dis::special_param_ambiguity(x86dis_insn *disasm_insn)
00702 {
00703 int regc=0, memc=0, segc=0;
00704 for (int i=0; i<3; i++) {
00705 switch (disasm_insn->op[i].type) {
00706 case X86_OPTYPE_SEG:
00707 segc++;
00708 case X86_OPTYPE_REG:
00709 case X86_OPTYPE_CRX:
00710 case X86_OPTYPE_DRX:
00711 case X86_OPTYPE_TRX:
00712 case X86_OPTYPE_STX:
00713 case X86_OPTYPE_MMX:
00714 regc++;
00715 break;
00716 case X86_OPTYPE_MEM:
00717 memc++;
00718 break;
00719 }
00720 }
00721 return (memc && !regc)
00722 || (memc && segc)
00723 || (strcmp(disasm_insn->name, "movzx") == 0)
00724 || (strcmp(disasm_insn->name, "movsx") == 0);
00725 }
00726
00727 void x86dis::str_op(char *opstr, int *opstrlen, x86dis_insn *insn, x86_insn_op *op, bool explicit_params)
00728 {
00729 const char *cs_default = get_cs(e_cs_default);
00730 const char *cs_number = get_cs(e_cs_number);
00731 const char *cs_symbol = get_cs(e_cs_symbol);
00732
00733 *opstrlen=0;
00734 switch (op->type) {
00735 case X86_OPTYPE_IMM: {
00736 CPU_ADDR a;
00737
00738 if ((insn->name[0]=='j') || strcmp(insn->name, "call")==0) {
00739 a.addr32.seg = seg;
00740 } else {
00741 a.addr32.seg = 0;
00742 }
00743 a.addr32.offset = op->imm;
00744 int slen;
00745 char *s=(addr_sym_func) ? addr_sym_func(a, &slen, addr_sym_func_context) : NULL;
00746 if (s) {
00747 memmove(opstr, s, slen);
00748 opstr[slen]=0;
00749 *opstrlen=slen;
00750 } else {
00751 char *g=opstr;
00752 strcpy(g, cs_number); g += strlen(cs_number);
00753 switch (op->size) {
00754 case 1:
00755 hexd(&g, 2, options, op->imm);
00756 break;
00757 case 2:
00758 hexd(&g, 4, options, op->imm);
00759 break;
00760 case 4:
00761 hexd(&g, 8, options, op->imm);
00762 break;
00763 }
00764 strcpy(g, cs_default); g += strlen(cs_default);
00765 }
00766 break;
00767 }
00768 case X86_OPTYPE_REG: {
00769 int j;
00770 switch (op->size) {
00771 case 1: j=0; break;
00772 case 2: j=1; break;
00773 case 4: j=2; break;
00774 default:
00775 j=-1;
00776 }
00777 if (j!=-1) sprintf(opstr, x86_regs[j][op->reg]);
00778 break;
00779 }
00780 case X86_OPTYPE_SEG:
00781 if (x86_segs[op->seg]) {
00782 sprintf(opstr, x86_segs[op->seg]);
00783 }
00784 break;
00785 case X86_OPTYPE_CRX:
00786 sprintf(opstr, "cr%d", op->crx);
00787 break;
00788 case X86_OPTYPE_DRX:
00789 sprintf(opstr, "dr%d", op->drx);
00790 break;
00791 case X86_OPTYPE_TRX:
00792 sprintf(opstr, "tr%d", op->trx);
00793 break;
00794 case X86_OPTYPE_STX:
00795 if (op->stx) {
00796 sprintf(opstr, "st(%d)", op->stx);
00797 } else {
00798 strcpy(opstr, "st");
00799 }
00800 break;
00801 case X86_OPTYPE_MMX:
00802 sprintf(opstr, "mm%d", op->mmx);
00803 break;
00804 case X86_OPTYPE_MEM: {
00805 char *d=opstr;
00806 int reg;
00807 if (explicit_params) {
00808 if (op->mem.floatptr) {
00809 switch (op->size) {
00810 case 4:
00811 d+=sprintf(d, "single ptr ");
00812 break;
00813 case 8:
00814 d+=sprintf(d, "double ptr ");
00815 break;
00816 case 10:
00817 d+=sprintf(d, "extended ptr ");
00818 break;
00819 }
00820 } else {
00821 switch (op->size) {
00822 case 1:
00823 d+=sprintf(d, "byte ptr ");
00824 break;
00825 case 2:
00826 d+=sprintf(d, "word ptr ");
00827 break;
00828 case 4:
00829 d+=sprintf(d, "dword ptr ");
00830 break;
00831 case 6:
00832 d+=sprintf(d, "pword ptr ");
00833 break;
00834 case 8:
00835 d+=sprintf(d, "qword ptr ");
00836 break;
00837 }
00838 }
00839 }
00840 if (insn->eaddrsize==X86_ADDRSIZE16) reg=1; else reg=2;
00841 if (insn->segprefix!=X86_PREFIX_NO) d+=sprintf(d, "%s%s:%s", x86_segs[(unsigned char)insn->segprefix], cs_symbol, cs_default);
00842 strcpy(d, cs_symbol); d += strlen(cs_symbol);
00843 *(d++)='[';
00844 strcpy(d, cs_default); d += strlen(cs_default);
00845
00846 int optimize_addr=options & X86DIS_STYLE_OPTIMIZE_ADDR;
00847 int first=1;
00848 if (optimize_addr && (op->mem.base!=X86_REG_NO) && (op->mem.base==op->mem.index)) {
00849 d+=sprintf(d, "%s%s*%s%d%s", x86_regs[reg][op->mem.index], cs_symbol, cs_number, op->mem.scale+1, cs_default);
00850 first=0;
00851 } else {
00852 if (op->mem.base!=X86_REG_NO) {
00853 d+=sprintf(d, "%s", x86_regs[reg][op->mem.base]);
00854 first=0;
00855 }
00856 if (op->mem.index!=X86_REG_NO) {
00857 if (!first) *(d++)='+';
00858 if ((op->mem.scale==1)) {
00859 d+=sprintf(d, "%s", x86_regs[reg][op->mem.index]);
00860 } else {
00861 d+=sprintf(d, "%s%s*%s%d%s", x86_regs[reg][op->mem.index], cs_symbol, cs_number, op->mem.scale, cs_default);
00862 }
00863 first=0;
00864 }
00865 }
00866 if ((!optimize_addr && op->mem.hasdisp) || (optimize_addr && op->mem.disp) || first) {
00867 CPU_ADDR a;
00868 a.addr32.seg = 0;
00869 a.addr32.offset=op->mem.disp;
00870 int slen;
00871 char *s=(addr_sym_func) ? addr_sym_func(a, &slen, addr_sym_func_context) : 0;
00872 if (s) {
00873 if (!first) {
00874 strcpy(d, cs_symbol); d += strlen(cs_symbol);
00875 *(d++)='+';
00876 strcpy(d, cs_default); d += strlen(cs_default);
00877 }
00878 memmove(d, s, slen);
00879 d+=slen;
00880 *opstrlen=d-opstr;
00881 } else {
00882 dword q;
00883 switch (op->mem.addrsize) {
00884 case X86_ADDRSIZE16:
00885 q=op->mem.disp;
00886 if (!first) {
00887 strcpy(d, cs_symbol); d += strlen(cs_symbol);
00888 if (op->mem.disp&0x80000000) {
00889 *(d++)='-';
00890 q=-q;
00891 } else *(d++)='+';
00892 }
00893 strcpy(d, cs_number); d += strlen(cs_number);
00894 hexd(&d, 4, options, q);
00895 strcpy(d, cs_default); d += strlen(cs_default);
00896 break;
00897 case X86_ADDRSIZE32:
00898 q=op->mem.disp;
00899 if (!first) {
00900 strcpy(d, cs_symbol); d += strlen(cs_symbol);
00901 if (op->mem.disp&0x80000000) {
00902 *(d++)='-';
00903 q=-q;
00904 } else *(d++)='+';
00905 }
00906 strcpy(d, cs_number); d += strlen(cs_number);
00907 hexd(&d, 8, options, q);
00908 strcpy(d, cs_default); d += strlen(cs_default);
00909 break;
00910 }
00911 }
00912 }
00913 strcpy(d, cs_symbol); d += strlen(cs_symbol);
00914 *(d++)=']';
00915 strcpy(d, cs_default); d += strlen(cs_default);
00916 if (*opstrlen)
00917 *opstrlen += strlen(cs_symbol) + 1 + strlen(cs_default);
00918 *d=0;
00919 break;
00920 }
00921 case X86_OPTYPE_FARPTR: {
00922 CPU_ADDR a;
00923
00924
00925
00926 a.addr32.seg = op->farptr.seg;
00927 a.addr32.offset = op->farptr.offset;
00928 int slen;
00929 char *s=(addr_sym_func) ? addr_sym_func(a, &slen, addr_sym_func_context) : 0;
00930 if (s) {
00931 memmove(opstr, s, slen);
00932 opstr[slen]=0;
00933 *opstrlen=slen;
00934 } else {
00935 char *g=opstr;
00936 hexd(&g, 4, options, op->farptr.seg);
00937 strcpy(g, cs_symbol); g += strlen(cs_symbol);
00938 *(g++)=':';
00939 strcpy(g, cs_default); g += strlen(cs_default);
00940 switch (op->size) {
00941 case 4:
00942 hexd(&g, 4, options, op->farptr.offset);
00943 break;
00944 case 6:
00945 hexd(&g, 8, options, op->farptr.offset);
00946 break;
00947 }
00948 }
00949 break;
00950 }
00951 default:
00952 opstr[0]=0;
00953 }
00954 }
00955
00956 void x86dis::str_format(char **str, char **format, char *p, char *n, char *op[3], int oplen[3], char stopchar, int print)
00957 {
00958 const char *cs_default = get_cs(e_cs_default);
00959 const char *cs_symbol = get_cs(e_cs_symbol);
00960
00961 char *f=*format;
00962 char *s=*str;
00963 while (*f) {
00964 if (*f==stopchar) break;
00965 switch (*f) {
00966 case '\t':
00967 if (print) do *(s++)=' '; while ((s-insnstr) % DIS_STYLE_TABSIZE);
00968 break;
00969 case DISASM_STRF_VAR:
00970 f++;
00971 if (print) {
00972 char *t=0;
00973 int tl=0;
00974 switch (*f) {
00975 case DISASM_STRF_PREFIX:
00976 t=p;
00977 break;
00978 case DISASM_STRF_NAME:
00979 t=n;
00980 break;
00981 case DISASM_STRF_FIRST:
00982 t=op[0];
00983 tl=oplen[0];
00984 break;
00985 case DISASM_STRF_SECOND:
00986 t=op[1];
00987 tl=oplen[1];
00988 break;
00989 case DISASM_STRF_THIRD:
00990 t=op[2];
00991 tl=oplen[2];
00992 break;
00993 }
00994 if (tl) {
00995 memmove(s, t, tl);
00996 s+=tl;
00997 *s=0;
00998 } else {
00999 strcpy(s, t);
01000 s += strlen(s);
01001 }
01002 }
01003 break;
01004 case DISASM_STRF_COND: {
01005 char *t=0;
01006 f++;
01007 switch (*f) {
01008 case DISASM_STRF_PREFIX:
01009 t=p;
01010 break;
01011 case DISASM_STRF_NAME:
01012 t=n;
01013 break;
01014 case DISASM_STRF_FIRST:
01015 t=op[0];
01016 break;
01017 case DISASM_STRF_SECOND:
01018 t=op[1];
01019 break;
01020 case DISASM_STRF_THIRD:
01021 t=op[2];
01022 break;
01023 }
01024 f+=2;
01025 if ((t) && (t[0])) {
01026 str_format(&s, &f, p, n, op, oplen, *(f-1), 1);
01027 } else {
01028 str_format(&s, &f, p, n, op, oplen, *(f-1), 0);
01029 }
01030 break;
01031 }
01032 default:
01033 if (print) {
01034 bool x = (strchr(",.-=+-*/[]()", *f) != NULL) && *f;
01035 if (x) { strcpy(s, cs_symbol); s += strlen(cs_symbol); }
01036 *(s++) = *f;
01037 if (x) { strcpy(s, cs_default); s += strlen(cs_default); }
01038 }
01039 }
01040 f++;
01041 }
01042 *s=0;
01043 *format=f;
01044 *str=s;
01045 }
01046
01047 char *x86dis::str(dis_insn *disasm_insn, int options)
01048 {
01049 return strf(disasm_insn, options, DISASM_STRF_DEFAULT_FORMAT);
01050 }
01051
01052 char *x86dis::strf(dis_insn *disasm_insn, int opt, char *format)
01053 {
01054 x86dis_insn *insn = (x86dis_insn*)disasm_insn;
01055 char prefix[64];
01056 char *p = prefix;
01057 options = opt;
01058 *p = 0;
01059 if (insn->lockprefix == X86_PREFIX_LOCK) p+=sprintf(p, "lock ");
01060 if (insn->repprefix == X86_PREFIX_REPZ) {
01061 p += sprintf(p, "repz ");
01062 } else if (insn->repprefix == X86_PREFIX_REPNZ) {
01063 p += sprintf(p, "repnz ");
01064 }
01065 if ((p != prefix) && (*(p-1) == ' ')) {
01066 p--;
01067 *p = 0;
01068 }
01069
01070 bool explicit_params = ((options & X86DIS_STYLE_EXPLICIT_MEMSIZE) ||
01071 special_param_ambiguity(insn));
01072
01073 char ops[3][512];
01074 char *op[3];
01075 int oplen[3];
01076
01077 if (options & DIS_STYLE_HIGHLIGHT) enable_highlighting();
01078 for (int i=0; i<3; i++) {
01079 op[i]=(char*)&ops[i];
01080 str_op(op[i], &oplen[i], insn, &insn->op[i], explicit_params);
01081 }
01082 char *s=insnstr;
01083 char n[32];
01084 switch (insn->eopsize) {
01085 case X86_OPSIZE16:
01086 sprintf(n, insn->name, 'w');
01087 break;
01088 case X86_OPSIZE32:
01089 sprintf(n, insn->name, 'd');
01090 break;
01091 default:
01092 strcpy(n, insn->name);
01093 break;
01094 }
01095 str_format(&s, &format, prefix, n, op, oplen, 0, 1);
01096 disable_highlighting();
01097 return insnstr;
01098 }
01099
01100 void x86dis::store(ht_object_stream *f)
01101 {
01102 PUT_INT_HEX(f, opsize);
01103 PUT_INT_HEX(f, addrsize);
01104 }
01105
01106 bool x86dis::validInsn(dis_insn *disasm_insn)
01107 {
01108 return !((x86dis_insn *)disasm_insn)->invalid;
01109 }
01110
01111
01112
01113
01114
01115 x86dis_vxd::x86dis_vxd()
01116 {
01117 }
01118
01119 x86dis_vxd::x86dis_vxd(int opsize, int addrsize)
01120 : x86dis(opsize, addrsize)
01121 {
01122 }
01123
01124 x86dis_vxd::~x86dis_vxd()
01125 {
01126 }
01127
01128 dis_insn *x86dis_vxd::decode(byte *code, byte maxlen, CPU_ADDR addr)
01129 {
01130 if ((maxlen >= 6) && (code[0] == 0xcd) && (code[1] == 0x20)) {
01131 insn.name = "VxDCall";
01132 insn.size = 6;
01133 vxd_t *v = find_vxd(vxds, *(word*)(code+4));
01134
01135 if (v) {
01136 insn.op[0].type = X86_OPTYPE_USER;
01137 insn.op[0].user[0].i = *(word*)(code+4);
01138 insn.op[0].user[1].p = v->name;
01139 char *vs = NULL;
01140 if (v->services) vs = find_vxd_service(v->services, *(word*)(code+2) & 0x7fff);
01141 if (vs) {
01142 insn.op[1].type = X86_OPTYPE_USER;
01143 insn.op[1].user[0].i = *(word*)(code+2);
01144 insn.op[1].user[1].p = vs;
01145 } else {
01146 insn.op[1].type = X86_OPTYPE_IMM;
01147 insn.op[1].size = 2;
01148 insn.op[1].imm = *(word*)(code+2);
01149 }
01150 } else {
01151 insn.op[0].type = X86_OPTYPE_IMM;
01152 insn.op[0].size = 2;
01153 insn.op[0].imm = *(word*)(code+4);
01154
01155 insn.op[1].type = X86_OPTYPE_IMM;
01156 insn.op[1].size = 2;
01157 insn.op[1].imm = *(word*)(code+2);
01158 }
01159 insn.op[2].type = X86_OPTYPE_EMPTY;
01160 insn.lockprefix = X86_PREFIX_NO;
01161 insn.repprefix = X86_PREFIX_NO;
01162 insn.segprefix = X86_PREFIX_NO;
01163 return &insn;
01164 }
01165 return x86dis::decode(code, maxlen, addr);
01166 }
01167
01168 OBJECT_ID x86dis_vxd::object_id() const
01169 {
01170 return ATOM_DISASM_X86_VXD;
01171 }
01172
01173 void x86dis_vxd::str_op(char *opstr, int *opstrlen, x86dis_insn *insn, x86_insn_op *op, bool explicit_params)
01174 {
01175 if (op->type == X86_OPTYPE_USER) {
01176 *opstrlen = 0;
01177 strcpy(opstr, (char*)op->user[1].p);
01178 } else {
01179 x86dis::str_op(opstr, opstrlen, insn, op, explicit_params);
01180 }
01181 }
01182
01183