/* jadecode.c: Copyright (C) Codemist Ltd., 1996. */ #include <stdio.h> #include <string.h> #include "machine.h" #include "tags.h" #include "cslerror.h" #include "externs.h" #include "read.h" #include "stream.h" #include "arith.h" #include "entries.h" #include "javahost.h" #include "javaglb.h" static struct { char *opname; } optable[211] = { "\x00""nop", /* 0 */ "\x00""aconst_null", /* 1 */ "\x00""iconst_m1", /* 2 */ "\x00""iconst_0", /* 3 */ "\x00""iconst_1", /* 4 */ "\x00""iconst_2", /* 5 */ "\x00""iconst_3", /* 6 */ "\x00""iconst_4", /* 7 */ "\x00""iconst_5", /* 8 */ "\x00""lconst_0", /* 9 */ "\x00""lconst_1", /* 10 */ "\x00""fconst_0", /* 11 */ "\x00""fconst_1", /* 12 */ "\x00""fconst_2", /* 13 */ "\x00""dconst_0", /* 14 */ "\x00""dconst_1", /* 15 */ "\x01""bipush", /* 16 */ "\x02""sipush", /* 17 */ "\x11""ldc1", /* 18 */ "\x12""ldc2", /* 19 */ "\x12""ldc2w", /* 20 */ "\x01""iload", /* 21 */ "\x01""lload", /* 22 */ "\x01""fload", /* 23 */ "\x01""dload", /* 24 */ "\x01""aload", /* 25 */ "\x00""iload_0", /* 26 */ "\x00""iload_1", /* 27 */ "\x00""iload_2", /* 28 */ "\x00""iload_3", /* 29 */ "\x00""lload_0", /* 30 */ "\x00""lload_1", /* 31 */ "\x00""lload_2", /* 32 */ "\x00""lload_3", /* 33 */ "\x00""fload_0", /* 34 */ "\x00""fload_1", /* 35 */ "\x00""fload_2", /* 36 */ "\x00""fload_3", /* 37 */ "\x00""dload_0", /* 38 */ "\x00""dload_1", /* 39 */ "\x00""dload_2", /* 40 */ "\x00""dload_3", /* 41 */ "\x00""aload_0", /* 42 */ "\x00""aload_1", /* 43 */ "\x00""aload_2", /* 44 */ "\x00""aload_3", /* 45 */ "\x00""iaload", /* 46 */ "\x00""laload", /* 47 */ "\x00""faload", /* 48 */ "\x00""daload", /* 49 */ "\x00""aaload", /* 50 */ "\x00""baload", /* 51 */ "\x00""caload", /* 52 */ "\x00""saload", /* 53 */ "\x01""istore", /* 54 */ "\x01""lstore", /* 55 */ "\x01""fstore", /* 56 */ "\x01""dstore", /* 57 */ "\x01""astore", /* 58 */ "\x00""istore_0", /* 59 */ "\x00""istore_1", /* 60 */ "\x00""istore_2", /* 61 */ "\x00""istore_3", /* 62 */ "\x00""lstore_0", /* 63 */ "\x00""lstore_1", /* 64 */ "\x00""lstore_2", /* 65 */ "\x00""lstore_3", /* 66 */ "\x00""fstore_0", /* 67 */ "\x00""fstore_1", /* 68 */ "\x00""fstore_2", /* 69 */ "\x00""fstore_3", /* 70 */ "\x00""dstore_0", /* 71 */ "\x00""dstore_1", /* 72 */ "\x00""dstore_2", /* 73 */ "\x00""dstore_3", /* 74 */ "\x00""astore_0", /* 75 */ "\x00""astore_1", /* 76 */ "\x00""astore_2", /* 77 */ "\x00""astore_3", /* 78 */ "\x00""iastore", /* 79 */ "\x00""lastore", /* 80 */ "\x00""fastore", /* 81 */ "\x00""dastore", /* 82 */ "\x00""aastore", /* 83 */ "\x00""bastore", /* 84 */ "\x00""castore", /* 85 */ "\x00""sastore", /* 86 */ "\x00""pop", /* 87 */ "\x00""pop2", /* 88 */ "\x00""dup", /* 89 */ "\x00""dup_x1", /* 90 */ "\x00""dup_x2", /* 91 */ "\x00""dup2", /* 92 */ "\x00""dup2_x1", /* 93 */ "\x00""dup2_x2", /* 94 */ "\x00""swap", /* 95 */ "\x00""iadd", /* 96 */ "\x00""ladd", /* 97 */ "\x00""fadd", /* 98 */ "\x00""dadd", /* 99 */ "\x00""isub", /* 100 */ "\x00""lsub", /* 101 */ "\x00""fsub", /* 102 */ "\x00""dsub", /* 103 */ "\x00""imul", /* 104 */ "\x00""lmul", /* 105 */ "\x00""fmul", /* 106 */ "\x00""dmul", /* 107 */ "\x00""idiv", /* 108 */ "\x00""ldiv", /* 109 */ "\x00""fdiv", /* 110 */ "\x00""ddiv", /* 111 */ "\x00""irem", /* 112 */ "\x00""lrem", /* 113 */ "\x00""frem", /* 114 */ "\x00""drem", /* 115 */ "\x00""ineg", /* 116 */ "\x00""lneg", /* 117 */ "\x00""fneg", /* 118 */ "\x00""dneg", /* 119 */ "\x00""ishl", /* 120 */ "\x00""ishr", /* 121 */ "\x00""iushr", /* 122 */ "\x00""lshl", /* 123 */ "\x00""lshr", /* 124 */ "\x00""lushr", /* 125 */ "\x00""iand", /* 126 */ "\x00""land", /* 127 */ "\x00""ior", /* 128 */ "\x00""lor", /* 129 */ "\x00""ixor", /* 130 */ "\x00""lxor", /* 131 */ "\x03""iinc", /* 132 */ "\x00""i2l", /* 133 */ "\x00""i2f", /* 134 */ "\x00""i2d", /* 135 */ "\x00""l2i", /* 136 */ "\x00""l2f", /* 137 */ "\x00""l2d", /* 138 */ "\x00""f2i", /* 139 */ "\x00""f2l", /* 140 */ "\x00""f2d", /* 141 */ "\x00""d2i", /* 142 */ "\x00""d2l", /* 143 */ "\x00""d2f", /* 144 */ "\x00""int2byte", /* 145 */ "\x00""int2char", /* 146 */ "\x00""int2short", /* 147 */ "\x00""lcmp", /* 148 */ "\x00""fcmpl", /* 149 */ "\x00""fcmpg", /* 150 */ "\x00""dcmpl", /* 151 */ "\x00""dcmpg", /* 152 */ "\x08""ifeq", /* 153 */ "\x08""ifne", /* 154 */ "\x08""iflt", /* 155 */ "\x08""ifge", /* 156 */ "\x08""ifgt", /* 157 */ "\x08""ifle", /* 158 */ "\x08""if_icmpeq", /* 159 */ "\x08""if_icmpne", /* 160 */ "\x08""if_icmplt", /* 161 */ "\x08""if_icmpge", /* 162 */ "\x08""if_icmpgt", /* 163 */ "\x08""if_icmple", /* 164 */ "\x08""if_acmpeq", /* 165 */ "\x08""if_acmpne", /* 166 */ "\x08""goto", /* 167 */ "\x08""jsr", /* 168 */ "\x01""ret", /* 169 */ "\x06""tableswitch", /* 170 */ "\x07""lookupswitch", /* 171 */ "\x00""ireturn", /* 172 */ "\x00""lreturn", /* 173 */ "\x00""freturn", /* 174 */ "\x00""dreturn", /* 175 */ "\x00""areturn", /* 176 */ "\x00""return", /* 177 */ "\x12""getstatic", /* 178 */ "\x12""putstatic", /* 179 */ "\x12""getfield", /* 180 */ "\x12""putfield", /* 181 */ "\x12""invokevirtual", /* 182 */ "\x12""invokenonvirtual", /* 183 */ "\x12""invokestatic", /* 184 */ "\x14""invokeinterface", /* 185 */ "\x00""<missing186>", /* 186 */ "\x12""new", /* 187 */ "\x01""newarray", /* 188 */ "\x12""anewarray", /* 189 */ "\x00""arraylength", /* 190 */ "\x00""athrow", /* 191 */ "\x12""checkcast", /* 192 */ "\x12""instanceof", /* 193 */ "\x00""monitorenter", /* 194 */ "\x00""monitorexit", /* 195 */ "\x01""wide", /* 196 */ "\x13""multinewarray", /* 197 */ "\x08""ifnull", /* 198 */ "\x08""ifnonnull", /* 199 */ "\x09""goto_w", /* 200 */ "\x09""jsr_w", /* 201 */ "\x00""breakpoint", /* 202 */ "\x00""<missing203>", /* 203 */ "\x00""<missing204>", /* 204 */ "\x00""<missing205>", /* 205 */ "\x00""<missing206>", /* 206 */ "\x00""<missing207>", /* 207 */ "\x00""<missing208>", /* 208 */ "\x02""ret_w", /* 209 */ "\x00""<missing >= 210>" }; static unsigned char *labtab; static void notelab(unsigned32 l) { if (l < 0x10000) labtab[l/8] |= 1 << (l%8); /* err_printf("notelab %d\n", l); */ } static int islab(unsigned32 l) { int b = 1 << l%8; /* err_printf("islab %d\n", l); */ if (l < 0x10000 && labtab[l/8] & b) { /* labtab[l/8] ^= b; */ return 1; } return 0; } static int reflab(unsigned32 l) { int b = 1 << l%8; if (l < 0x10000 && labtab[l/8] & b) { err_printf("L%.4x", l); return 1; } return 0; } #define ztos16(w) (((unsigned32)(w) ^ 0x8000) - 0x8000) static void decode_lit(unsigned32 n, Cp_Info *cp, unsigned32 cplen) { for (;;) { if (n == 0 || n >= cplen) { err_printf("<bad literal 0x%x>", n); return; } else switch (cp[n].tag) { case CONSTANT_Class: err_printf("Class"); goto redo; case CONSTANT_FieldRef: err_printf("FieldRef"); goto redo2; case CONSTANT_MethodRef: err_printf("MethodRef"); goto redo2; case CONSTANT_InterfaceMethodRef: err_printf("InterfaceMethodRef"); goto redo2; case CONSTANT_String: err_printf("String"); goto redo; case CONSTANT_Integer: err_printf("Integer:%d",n); return; case CONSTANT_Float: err_printf("Float:%d",n); return; case CONSTANT_Long: err_printf("Long:%d",n); return; case CONSTANT_Double: err_printf("Double:%d",n); return; case CONSTANT_Utf8: err_printf("Utf8[%d'%*s']", n, cp[n].len, cp[n].u.utf8); return; case CONSTANT_Unicode: err_printf("Unicode:%d",n); return; case CONSTANT_NameAndType: err_printf("NameAndType"); goto redo2; default: err_printf("<unknown literal[%.4x] %d>", n, cp[n].tag); return; } redo: err_printf("[%d]:", n); n = cp[n].u.val; continue; redo2: err_printf("[%d]:<", n); decode_lit(cp[n].u.val, cp, cplen); err_printf(","); decode_lit(cp[n].len, cp, cplen); err_printf(">"); return; } } char *jdecodeopname(unsigned32 op) { if (op >= 210) op = 210; return optable[op].opname+1; } void javadecode(unsigned8 *code, unsigned32 len, Cp_Info *cp, unsigned32 cplen) { unsigned8 *p; if (labtab == 0) labtab = (unsigned char *)jmalloc(0x10000/8); memset(labtab, 0, 0x10000/8); for (p = code; p < code+len;) { unsigned32 op = *p++; if (op >= 210) op = 210; switch (optable[op].opname[0]) { default: break; case 0x11: case 0x01: p++; break; case 0x12: case 0x02: p += 2; break; case 0x08: notelab(p-1-code + ztos16(p[0]<<8 | p[1])); p += 2; break; case 0x03: p += 2; break; case 0x13: p += 3; break; case 0x14: case 0x04: p += 4; break; case 0x09: notelab(p-1-code + (p[0]<<24 | p[1]<<16 | p[2]<<8 | p[3])); p += 4; break; case 0x06: ("\ttableswitch!"); break; case 0x07: ("\tlookupswitch!"); break; } } for (p = code; p < code+len;) { unsigned32 op = *p++; unsigned32 off; if (op >= 210) op = 210; if (islab(p-1 - code)) err_printf("L%.4x:", p-1 - code); err_printf("\t%s", optable[op].opname+1); if (optable[op].opname[0] != 0x00 && strlen(optable[op].opname+1) < 8) err_printf("\t"); switch (optable[op].opname[0]) { default: break; case 0x01: err_printf("\t%d", *p++); break; case 0x11: err_printf("\t"); decode_lit(*p++, cp, cplen); break; case 0x02: err_printf("\t0x%.4x", p[0]<<8 | p[1]); p += 2; break; case 0x12: err_printf("\t"); decode_lit(p[0]<<8 | p[1], cp, cplen); p += 2; break; case 0x08: off = ztos16(p[0]<<8 | p[1]); err_printf("\t"); if (!reflab(p-1-code+off)) err_printf("$+0x%.4x", off); p += 2; break; case 0x03: err_printf("\t%d,%d", p[0], p[1]); p += 2; break; case 0x13: err_printf("\t"); decode_lit(p[0]<<8 | p[1], cp, cplen); err_printf(",%d", p[2]); p += 3; break; case 0x14: err_printf("\t"); decode_lit(p[0]<<8 | p[1], cp, cplen); err_printf(",%d,%d", p[2], p[3]); p += 4; break; case 0x04: err_printf("\t0x%.8x", p[0]<<24 | p[1]<<16 | p[2]<<8 | p[3]); p += 4; break; case 0x09: off = p[0]<<24 | p[1]<<16 | p[2]<<8 | p[3]; err_printf("\t(big)"); if (!reflab(p-1-code+off)) err_printf("\t$+0x%.8x", off); p += 4; break; case 0x06: err_printf("\tswitch!"); break; case 0x07: err_printf("\tswitch!"); break; } err_printf("\n"); } } /* end of jadecode.c */