Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

x86dis.cc

Go to the documentation of this file.
00001 /*
00002  *      HT Editor
00003  *      x86dis.cc
00004  *
00005  *      Copyright (C) 1999-2002 Stefan Weyergraf (stefan@weyergraf.de)
00006  *
00007  *      This program is free software; you can redistribute it and/or modify
00008  *      it under the terms of the GNU General Public License version 2 as
00009  *      published by the Free Software Foundation.
00010  *
00011  *      This program is distributed in the hope that it will be useful,
00012  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *      GNU General Public License for more details.
00015  *
00016  *      You should have received a copy of the GNU General Public License
00017  *      along with this program; if not, write to the Free Software
00018  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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  *      CLASS x86dis
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 /* initialize */
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 /* reg */
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 /* mem */
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 /*                                      fprintf(stderr, "special.data=%d, m=%d, mkreg(m)=%d, mkrm(m)=%d\n", special.data, m, mkreg(m), mkrm(m));*/
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 /* direct address without ModR/M */
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 /* reg of ModR/M picks control register */
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 /* reg of ModR/M picks debug register */
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 /* ModR/M (general reg or memory) */
00285                         decode_modrm(op, xop->size, (xop->size!=SIZE_P), 1, 0);
00286                         break;
00287                 }
00288                 case TYPE_F: {
00289 /* r/m of ModR/M picks a fpu register */
00290                         op->type=X86_OPTYPE_STX;
00291                         op->size=10;
00292                         op->stx=mkrm(getmodrm());
00293                         break;
00294                 }
00295                 case TYPE_Fx: {
00296 /* extra picks a fpu register */
00297                         op->type=X86_OPTYPE_STX;
00298                         op->size=10;
00299                         op->stx=xop->extra;
00300                         break;
00301                 }
00302                 case TYPE_G: {
00303 /* reg of ModR/M picks general register */
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 /* signed immediate */
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 /* unsigned immediate */
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 /* fixed immediate */
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 /* relative branch offset */
00362                         op->type=X86_OPTYPE_IMM;
00363 //                      op->size=esizeaddr(xop->extendedsize);
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 /* ModR/M (memory only) */
00381                         decode_modrm(op, xop->size, 0, 1, 0);
00382                         break;
00383                 }
00384                 case TYPE_O: {
00385 /* direct memory without ModR/M */
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 /* reg of ModR/M picks MMX register */
00407                         op->type=X86_OPTYPE_MMX;
00408                         op->size=8;
00409                         op->mmx=mkreg(getmodrm());
00410                         break;
00411                 }
00412                 case TYPE_Q: {
00413 /* ModR/M (MMX reg or memory) */
00414                         decode_modrm(op, xop->size, 1, 1, 1);
00415                         break;
00416                 }
00417                 case TYPE_R: {
00418 /* rm of ModR/M picks general register */
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 /* extra picks register */
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 /* reg of ModR/M picks segment register */
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 /* extra picks segment register */
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 /* reg of ModR/M picks test register */
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;    // 1/2/3/4/5/6/8/10/12/15
00599         avg_look_ahead = 24;     // 1/2/3/4/6/8/12/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                         // FIXME: hack
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; // FIXME: not ok
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 /*                      a.addr32.seg = op->farptr.seg;
00924                         a.addr32.offset = op->farptr.offset;
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];       /* FIXME: possible buffer overflow ! */
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  *      CLASS x86dis_vxd
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 

Generated on Fri May 7 21:15:46 2004 by doxygen 1.3.5