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 "javadis.h"
00025
00026 #include <stdio.h>
00027 #include <string.h>
00028
00029
00030
00031
00032
00033 javadis::javadis()
00034 {
00035 }
00036
00037 javadis::javadis(java_token_func tf, void *c)
00038 {
00039 token_func = tf;
00040 context = c;
00041 }
00042
00043 javadis::~javadis()
00044 {
00045 }
00046
00047 dis_insn *javadis::decode(byte *code, int Maxlen, CPU_ADDR Addr)
00048 {
00049 ocodep = code;
00050
00051 codep = ocodep;
00052 maxlen = Maxlen;
00053 addr = Addr.addr32.offset;
00054 memset(&insn, 0, sizeof(insn));
00055 insn.invalid = false;
00056
00057 insn.opcode = getbyte();
00058 if (insn.opcode == JAVA_WIDE_OPCODE) {
00059 insn.wideopcode = true;
00060 insn.opcode = getbyte();
00061 } else {
00062 insn.wideopcode = false;
00063 }
00064 decode_insn(&java_insns[insn.opcode]);
00065
00066 if (insn.invalid) {
00067 insn.name = "db";
00068 insn.size = 1;
00069 insn.op[0].type = JAVA_OPTYPE_IMM;
00070 insn.op[0].size = 1;
00071 insn.op[0].imm = *code;
00072 for (int i=1; i<JAVAINSN_MAX_PARAM_COUNT; i++) insn.op[i].type=JAVA_OPTYPE_EMPTY;
00073 } else {
00074 insn.size=codep-ocodep;
00075 }
00076 return &insn;
00077 }
00078
00079 void javadis::decode_insn(javaopc_insn *xinsn)
00080 {
00081 if (!xinsn->name) {
00082 invalidate();
00083 return;
00084 }
00085 insn.name = xinsn->name;
00086 for (int i=0; i<JAVAINSN_MAX_PARAM_COUNT; i++) {
00087 decode_op(xinsn->optype[i], insn.wideopcode, &insn.op[i]);
00088 }
00089 }
00090
00091 void javadis::decode_op(int optype, bool wideopc, java_insn_op *op)
00092 {
00093 bool widesize = wideopc || (JOPC_SIZE(optype) == JOPC_SIZE_WIDE);
00094 switch (JOPC_TYPE(optype)) {
00095 case JOPC_TYPE_CHAR:
00096 op->type = JAVA_OPTYPE_IMM;
00097 op->size = 2;
00098 op->imm = getword();
00099 break;
00100 case JOPC_TYPE_BYTE:
00101 op->type = JAVA_OPTYPE_IMM;
00102 op->size = 1;
00103 op->imm = getbyte();
00104 break;
00105 case JOPC_TYPE_SHORT:
00106 op->type = JAVA_OPTYPE_IMM;
00107 op->size = 2;
00108 op->imm = getword();
00109 break;
00110 case JOPC_TYPE_INT:
00111 op->type = JAVA_OPTYPE_IMM;
00112 op->size = 4;
00113 op->imm = getdword();
00114 break;
00115 case JOPC_TYPE_CONST:
00116 op->type = JAVA_OPTYPE_CONST;
00117 if (widesize) {
00118 op->size = 2;
00119 op->imm = getword();
00120 } else {
00121 op->size = 1;
00122 op->imm = getbyte();
00123 }
00124 break;
00125 case JOPC_TYPE_LOCAL:
00126 op->type = JAVA_OPTYPE_IMM;
00127 if (widesize) {
00128 op->size = 2;
00129 op->imm = getword();
00130 } else {
00131 op->size = 1;
00132 op->imm = getbyte();
00133 }
00134 break;
00135 case JOPC_TYPE_LABEL:
00136 op->type = JAVA_OPTYPE_LABEL;
00137 if (widesize) {
00138 op->size = 4;
00139
00140 op->label = addr + (int)getdword() - op->size - 1;
00141 } else {
00142 op->size = 2;
00143
00144 op->label = addr + (short)getword() - op->size - 1;
00145 }
00146 break;
00147 default:
00148 op->type = JAVA_OPTYPE_EMPTY;
00149 }
00150 }
00151
00152 dis_insn *javadis::duplicateInsn(dis_insn *disasm_insn)
00153 {
00154 javadis_insn *insn = (javadis_insn *)malloc(sizeof (javadis_insn));
00155 *insn = *(javadis_insn *)disasm_insn;
00156 return insn;
00157 }
00158
00159 byte javadis::getbyte()
00160 {
00161 if (codep-ocodep+1<=maxlen) {
00162 addr++;
00163 return *(codep++);
00164 } else {
00165 invalidate();
00166 return 0;
00167 }
00168 }
00169
00170 word javadis::getword()
00171 {
00172 if (codep-ocodep+2<=maxlen) {
00173 word w;
00174 addr += 2;
00175 w = codep[1] | (codep[0]<<8);
00176 codep += 2;
00177 return w;
00178 } else {
00179 invalidate();
00180 return 0;
00181 }
00182 }
00183
00184 dword javadis::getdword()
00185 {
00186 if (codep-ocodep+4<=maxlen) {
00187 dword w;
00188 addr += 4;
00189 w = codep[3] | (codep[2]<<8) | (codep[1]<<16) | (codep[0]<<24);
00190 codep += 4;
00191 return w;
00192 } else {
00193 invalidate();
00194 return 0;
00195 }
00196 }
00197
00198 void javadis::getOpcodeMetrics(int &min_length, int &max_length, int &min_look_ahead, int &avg_look_ahead, int &addr_align)
00199 {
00200 min_length = 1;
00201 max_length = 6;
00202 min_look_ahead = 120;
00203 avg_look_ahead = 24;
00204 addr_align = 1;
00205 }
00206
00207 char *javadis::getName()
00208 {
00209 return "Java/Disassembler";
00210 }
00211
00212 byte javadis::getSize(dis_insn *disasm_insn)
00213 {
00214 return ((javadis_insn*)disasm_insn)->size;
00215 }
00216
00217 void javadis::invalidate()
00218 {
00219 insn.invalid = true;
00220 }
00221
00222 int javadis::load(ht_object_stream *f)
00223 {
00224 return f->get_error();
00225 }
00226
00227 OBJECT_ID javadis::object_id() const
00228 {
00229 return ATOM_DISASM_JAVA;
00230 }
00231
00232 void javadis::str_op(char *opstr, int *opstrlen, javadis_insn *insn, java_insn_op *op)
00233 {
00234 const char *cs_default = get_cs(e_cs_default);
00235 const char *cs_number = get_cs(e_cs_number);
00236
00237 const char *cs_comment = get_cs(e_cs_comment);
00238
00239 *opstrlen=0;
00240 switch (op->type) {
00241 case JAVA_OPTYPE_CONST: {
00242 char *g=opstr;
00243 strcpy(g, cs_comment); g += strlen(cs_comment);
00244 g += token_func(g, 1024, op->imm, context);
00245 *(g++) = ' ';
00246 strcpy(g, cs_number); g += strlen(cs_number);
00247 switch (op->size) {
00248 case 1:
00249 hexd(&g, 2, options, op->imm);
00250 break;
00251 case 2:
00252 hexd(&g, 4, options, op->imm);
00253 break;
00254 case 4:
00255 hexd(&g, 8, options, op->imm);
00256 break;
00257 }
00258 break;
00259 }
00260 case JAVA_OPTYPE_LABEL: {
00261 CPU_ADDR a;
00262 a.addr32.offset=op->imm;
00263 int slen;
00264 char *s=(addr_sym_func) ? addr_sym_func(a, &slen, addr_sym_func_context) : NULL;
00265 if (s) {
00266 memmove(opstr, s, slen);
00267 opstr[slen]=0;
00268 *opstrlen=slen;
00269 } else {
00270 char *g=opstr;
00271 strcpy(g, cs_number); g += strlen(cs_number);
00272 switch (op->size) {
00273 case 1:
00274 hexd(&g, 2, options, op->imm);
00275 break;
00276 case 2:
00277 hexd(&g, 4, options, op->imm);
00278 break;
00279 case 4:
00280 hexd(&g, 8, options, op->imm);
00281 break;
00282 }
00283 strcpy(g, cs_default); g += strlen(cs_default);
00284 }
00285 break;
00286 }
00287 case JAVA_OPTYPE_IMM: {
00288 CPU_ADDR a;
00289 a.addr32.offset=op->imm;
00290 char *g=opstr;
00291 strcpy(g, cs_number); g += strlen(cs_number);
00292 switch (op->size) {
00293 case 1:
00294 hexd(&g, 2, options, op->imm);
00295 break;
00296 case 2:
00297 hexd(&g, 4, options, op->imm);
00298 break;
00299 case 4:
00300 hexd(&g, 8, options, op->imm);
00301 break;
00302 }
00303 strcpy(g, cs_default); g += strlen(cs_default);
00304 break;
00305 }
00306 default:
00307 opstr[0]=0;
00308 }
00309 }
00310
00311 void javadis::str_format(char **str, char **format, char *p, char *n, char *op[3], int oplen[3], char stopchar, int print)
00312 {
00313
00314 const char *cs_default = get_cs(e_cs_default);
00315 const char *cs_symbol = get_cs(e_cs_symbol);
00316
00317 char *f=*format;
00318 char *s=*str;
00319 while (*f) {
00320 if (*f==stopchar) break;
00321 switch (*f) {
00322 case '\t':
00323 if (print) do *(s++)=' '; while ((s-insnstr) % 16);
00324 break;
00325 case DISASM_STRF_VAR:
00326 f++;
00327 if (print) {
00328 char *t=0;
00329 int tl=0;
00330 switch (*f) {
00331 case DISASM_STRF_PREFIX:
00332 t=p;
00333 break;
00334 case DISASM_STRF_NAME:
00335 t=n;
00336 break;
00337 case DISASM_STRF_FIRST:
00338 t=op[0];
00339 tl=oplen[0];
00340 break;
00341 case DISASM_STRF_SECOND:
00342 t=op[1];
00343 tl=oplen[1];
00344 break;
00345 case DISASM_STRF_THIRD:
00346 t=op[2];
00347 tl=oplen[2];
00348 break;
00349 }
00350 if (tl) {
00351 memmove(s, t, tl);
00352 s+=tl;
00353 *s=0;
00354 } else {
00355 strcpy(s, t);
00356 s += strlen(s);
00357 }
00358 }
00359 break;
00360 case DISASM_STRF_COND: {
00361 char *t=0;
00362 f++;
00363 switch (*f) {
00364 case DISASM_STRF_PREFIX:
00365 t=p;
00366 break;
00367 case DISASM_STRF_NAME:
00368 t=n;
00369 break;
00370 case DISASM_STRF_FIRST:
00371 t=op[0];
00372 break;
00373 case DISASM_STRF_SECOND:
00374 t=op[1];
00375 break;
00376 case DISASM_STRF_THIRD:
00377 t=op[2];
00378 break;
00379 }
00380 f+=2;
00381 if ((t) && (t[0])) {
00382 str_format(&s, &f, p, n, op, oplen, *(f-1), 1);
00383 } else {
00384 str_format(&s, &f, p, n, op, oplen, *(f-1), 0);
00385 }
00386 break;
00387 }
00388 default:
00389 if (print) {
00390 bool x = (strchr(",.-=+-*/[]()", *f) != NULL) && *f;
00391 if (x) { strcpy(s, cs_symbol); s += strlen(cs_symbol); }
00392 *(s++) = *f;
00393 if (x) { strcpy(s, cs_default); s += strlen(cs_default); }
00394 }
00395 }
00396 f++;
00397 }
00398 *s=0;
00399 *format=f;
00400 *str=s;
00401 }
00402
00403 char *javadis::str(dis_insn *disasm_insn, int options)
00404 {
00405 return strf(disasm_insn, options, DISASM_STRF_DEFAULT_FORMAT);
00406 }
00407
00408 char *javadis::strf(dis_insn *disasm_insn, int opt, char *format)
00409 {
00410 javadis_insn *insn = (javadis_insn*)disasm_insn;
00411 char prefix[64];
00412 char *p = prefix;
00413 options = opt;
00414 *p = 0;
00415
00416 char ops[3][512];
00417 char *op[3];
00418 int oplen[3];
00419
00420 if (options & DIS_STYLE_HIGHLIGHT) enable_highlighting();
00421 for (int i=0; i<3; i++) {
00422 op[i]=(char*)&ops[i];
00423 str_op(op[i], &oplen[i], insn, &insn->op[i]);
00424 }
00425 char *s=insnstr;
00426 str_format(&s, &format, prefix, insn->name, op, oplen, 0, 1);
00427 disable_highlighting();
00428 return insnstr;
00429 }
00430
00431 void javadis::store(ht_object_stream *f)
00432 {
00433 }
00434
00435 bool javadis::validInsn(dis_insn *disasm_insn)
00436 {
00437 return !((javadis_insn *)disasm_insn)->invalid;
00438 }