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

javadis.cc

Go to the documentation of this file.
00001 /*
00002  *      HT Editor
00003  *      javadis.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 "javadis.h"
00025 
00026 #include <stdio.h>
00027 #include <string.h>
00028 
00029 /*
00030  *      CLASS javadis
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 /* initialize */
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                                 // FIXME: sint32
00140                                 op->label = addr + (int)getdword() - op->size - 1;
00141                         } else {
00142                                 op->size = 2;
00143                                 // FIXME: sint16
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 //      const char *cs_symbol = get_cs(e_cs_symbol);
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];       /* FIXME: possible buffer overflow ! */
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 }

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