00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
00155 const char *cs_number = get_cs(e_cs_number);
00156
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
00163
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
00242 return 0;
00243 }
00244
00245 bool ILDisassembler::validInsn(dis_insn *disasm_insn)
00246 {
00247 return ((ILDisInsn *)disasm_insn)->valid;
00248 }
00249
00250
00251