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

ildis.cc

Go to the documentation of this file.
00001 /*
00002  *      HT Editor
00003  *      ildis.cc
00004  *
00005  *      Copyright (C) 1999-2002 Sebastian Biallas (sb@web-productions.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 <string.h>
00022 #include <stdlib.h>
00023 
00024 #include "global.h"
00025 #include "htendian.h"
00026 #include "ildis.h"
00027 #include "ilopc.h"
00028 
00029 
00030 ILDisassembler::ILDisassembler(char* (*sf)(dword string_ofs, void *context), char* (*tf)(dword token, void *context), void *ctx)
00031 {
00032         string_func = sf;
00033         token_func = tf;
00034         context = ctx;
00035 }
00036 
00037 ILDisassembler::~ILDisassembler()
00038 {
00039 }
00040 
00041 dis_insn *ILDisassembler::decode(byte *code, int maxlen, CPU_ADDR addr)
00042 {
00043         insn.valid = false;
00044         insn.prefix = NULL;
00045         insn.size = 0;
00046         insn.data = *code;
00047 restart:
00048         if (!maxlen) {
00049                 return (dis_insn *)&insn;
00050         }
00051         insn.opcode = &il_opcode_table[*code];
00052         insn.size += insn.opcode->size;
00053         if (insn.size > maxlen) {
00054                 insn.size = 1;
00055                 insn.valid = false;
00056                 return (dis_insn *)&insn;
00057         }
00058         insn.op = insn.opcode->op;
00059         switch (insn.op) {
00060                 case IL_OPCODE_ARGS_INVALID:
00061                         return (dis_insn *)&insn;
00062                 case IL_OPCODE_ARGS_NONE:
00063                         break;
00064                 case IL_OPCODE_ARGS_PREFIX:
00065                         insn.opcode = NULL;
00066                         code++;
00067                         if (*code < MAX_IL_OPCODE_PREFIX) {
00068                                 insn.prefix = &il_prefix_opcode_table[*code];
00069                                 insn.size--;
00070                                 code++;
00071                                 goto restart;
00072                         } else {
00073                                 return (dis_insn *)&insn;
00074                         }
00075                 case IL_OPCODE_ARGS_SHORT_JUMP: {
00076                         int c = ((char)code[1]);
00077                         insn.data = addr.addr32.offset+2+c;
00078                         break;
00079                 }
00080                 case IL_OPCODE_ARGS_LONG_JUMP: {
00081                         int c = create_host_int(code+1, 4, little_endian);
00082                         insn.data = addr.addr32.offset+5+c;
00083                         break;
00084                 }
00085                 case IL_OPCODE_ARGS_UINT16: {
00086                         word w = create_host_int(code+1, 2, little_endian);
00087                         insn.data = w;
00088                         break;
00089                 }
00090                 case IL_OPCODE_ARGS_INT16: {
00091                         word w = create_host_int(code+1, 2, little_endian);
00092                         insn.data = (int)((short)w);
00093                         break;
00094                 }
00095                 case IL_OPCODE_ARGS_UINT8: {
00096                         insn.data = (byte)code[1];
00097                         break;
00098                 }
00099                 case IL_OPCODE_ARGS_INT8:
00100                 case IL_OPCODE_ARGS_SHORT_VAR:
00101                 case IL_OPCODE_ARGS_SHORT_ARG: {
00102                         insn.data = (int)((char)code[1]);
00103                         break;
00104                 }
00105                 case IL_OPCODE_ARGS_TOKEN:
00106                 case IL_OPCODE_ARGS_NEW:
00107                 case IL_OPCODE_ARGS_CALL:
00108                 case IL_OPCODE_ARGS_CALLVIRT:
00109                 case IL_OPCODE_ARGS_INT32:
00110                 case IL_OPCODE_ARGS_STRING:
00111                         insn.data = create_host_int(code+1, 4, little_endian);
00112                         break;
00113         }
00114         insn.valid = true;
00115         return (dis_insn *)&insn;
00116 }
00117 
00118 dis_insn *ILDisassembler::duplicateInsn(dis_insn *disasm_insn)
00119 {
00120         ILDisInsn *insn = (ILDisInsn *)malloc(sizeof (ILDisInsn));
00121         *insn = *(ILDisInsn *)disasm_insn;
00122         return insn;
00123 }
00124 
00125 void ILDisassembler::getOpcodeMetrics(int &min_length, int &max_length, int &min_look_ahead, int &avg_look_ahead, int &addr_align)
00126 {
00127         // FIXME
00128         min_length = 1;
00129         max_length = 10;
00130         min_look_ahead = 120;
00131         avg_look_ahead = 24;
00132         addr_align = 1;
00133 }
00134 
00135 byte ILDisassembler::getSize(dis_insn *disasm_insn)
00136 {
00137         return ((ILDisInsn*)disasm_insn)->size;
00138 }
00139 
00140 char *ILDisassembler::getName()
00141 {
00142         return "IL/Disassembler";
00143 }
00144 
00145 char *ILDisassembler::str(dis_insn *disasm_insn, int style)
00146 {
00147         return strf(disasm_insn, style, "");
00148 }
00149 
00150 char *ILDisassembler::strf(dis_insn *disasm_insn, int style, char *format)
00151 {
00152         if (style & DIS_STYLE_HIGHLIGHT) enable_highlighting();
00153 
00154 //      const char *cs_default = get_cs(e_cs_default);
00155         const char *cs_number = get_cs(e_cs_number);
00156 //      const char *cs_symbol = get_cs(e_cs_symbol);
00157         const char *cs_string = get_cs(e_cs_string);
00158 
00159         ILDisInsn *dis_insn = (ILDisInsn *) disasm_insn;
00160         
00161         if (!dis_insn->valid) {
00162 //              is_invalid:
00163 //          assert(dis_insn->size==1);
00164                 sprintf(insnstr, "db              %s0x%02x", cs_number, dis_insn->data);
00165         } else {
00166                 switch (dis_insn->op) {
00167                         case IL_OPCODE_ARGS_NONE:
00168                                 sprintf(insnstr, "%-15s", dis_insn->opcode->name);
00169                                 break;
00170                         case IL_OPCODE_ARGS_UINT8: {
00171                                 sprintf(insnstr, "%-15s %s0x%02x", dis_insn->opcode->name, cs_number, dis_insn->data);
00172                                 break;
00173                         }
00174                         case IL_OPCODE_ARGS_INT8:
00175                         case IL_OPCODE_ARGS_SHORT_VAR:
00176                         case IL_OPCODE_ARGS_SHORT_ARG: {
00177                                 sprintf(insnstr, "%-15s %s0x%x", dis_insn->opcode->name, cs_number, dis_insn->data);
00178                                 break;
00179                         }
00180                         case IL_OPCODE_ARGS_INT32:
00181                                 sprintf(insnstr, "%-15s %s0x%08x", dis_insn->opcode->name, cs_number, dis_insn->data);
00182                                 break;                    
00183                         case IL_OPCODE_ARGS_CALL:
00184                         case IL_OPCODE_ARGS_CALLI:
00185                         case IL_OPCODE_ARGS_CALLVIRT:
00186                         case IL_OPCODE_ARGS_NEW:
00187                         case IL_OPCODE_ARGS_TOKEN: {
00188                                 dword token = dis_insn->data;                    
00189                                 char *tokenstr = NULL;
00190                                 if (token_func) {
00191                                         tokenstr = token_func(token, context);
00192                                         if (tokenstr) {
00193                                                 sprintf(insnstr, "%-15s %s", dis_insn->opcode->name, tokenstr);
00194                                                 break;
00195                                         }
00196                                 }
00197                                 sprintf(insnstr, "%-15s %s0x%08x", dis_insn->opcode->name, cs_number, token);
00198                                 break;
00199                         }
00200                         case IL_OPCODE_ARGS_STRING: {
00201                                 if ((dis_insn->data & IL_META_TOKEN_MASK) == IL_META_TOKEN_STRING) {
00202                                         dword strofs = dis_insn->data & (~IL_META_TOKEN_MASK);
00203                                         char *str = NULL;
00204                                         if (string_func) {
00205                                                 str = string_func(strofs, context);
00206                                         }
00207                                         if (str) {
00208                                                 sprintf(insnstr, "%-15s %s\"%s\"", dis_insn->opcode->name, cs_string, str);
00209                                                 break;
00210                                         }
00211                                 }
00212                                 sprintf(insnstr, "%-15s %s0x%08x", dis_insn->opcode->name, cs_number, dis_insn->data);
00213                                 break;
00214                         }
00215                         case IL_OPCODE_ARGS_LONG_JUMP:
00216                         case IL_OPCODE_ARGS_SHORT_JUMP: {
00217                                 CPU_ADDR caddr;
00218                                 caddr.addr32.offset = (dword)dis_insn->data;
00219                                 int slen;
00220                                 char *s = (addr_sym_func) ? addr_sym_func(caddr, &slen, addr_sym_func_context) : NULL;
00221                                 if (s) {
00222                                         char *p = insnstr + sprintf(insnstr, "%-15s ", dis_insn->opcode->name);
00223                                         memmove(p, s, slen);
00224                                         p[slen] = 0;
00225                                 } else {
00226                                         sprintf(insnstr, "%-15s %s0x%08x", dis_insn->opcode->name, cs_number, dis_insn->data);
00227                                 }
00228                                 break;
00229                         }
00230                         default:
00231                                 sprintf(insnstr, "%-15s [unsupported paramtype]", dis_insn->opcode->name);
00232                 }
00233         }
00234         
00235         disable_highlighting();
00236         return insnstr;     
00237 }
00238 
00239 OBJECT_ID ILDisassembler::object_id() const
00240 {
00241         // FIXME
00242         return 0;
00243 }
00244 
00245 bool ILDisassembler::validInsn(dis_insn *disasm_insn)
00246 {
00247         return ((ILDisInsn *)disasm_insn)->valid;
00248 }
00249 
00250         
00251 

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